GCC Code Coverage Report


Directory: ./
File: sql/rpl_replica.cc
Date: 2022-12-13 11:44:05
Exec Total Coverage
Lines: 4235 4672 90.6%
Branches: 5602 10307 54.4%

Line Branch Exec Source
1 /* Copyright (c) 2000, 2022, Oracle and/or its affiliates.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License, version 2.0,
5 as published by the Free Software Foundation.
6
7 This program is also distributed with certain software (including
8 but not limited to OpenSSL) that is licensed under separate terms,
9 as designated in a particular file or component or in included license
10 documentation. The authors of MySQL hereby grant you an additional
11 permission to link the program and your derivative works with the
12 separately licensed software that they have included with MySQL.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License, version 2.0, for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
22
23 /**
24 @addtogroup Replication
25 @{
26
27 @file sql/rpl_replica.cc
28
29 @brief Code to run the io thread and the sql thread on the
30 replication slave.
31 */
32
33 #include "sql/rpl_replica.h"
34
35 #include "my_config.h"
36
37 #ifdef WITH_WSREP
38 #include "mysql/components/services/log_builtins.h"
39 #include "service_wsrep.h"
40 #include "wsrep_mysqld.h"
41 #include "wsrep_trans_observer.h"
42 #endif /* WITH_WSREP */
43
44 #include <errno.h>
45 #include <fcntl.h>
46 #include <math.h>
47 #include <signal.h>
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #include <time.h>
52
53 #include "include/compression.h"
54 #include "include/mutex_lock.h"
55 #include "mysql/components/services/bits/psi_bits.h"
56 #include "mysql/components/services/bits/psi_memory_bits.h"
57 #include "mysql/components/services/bits/psi_stage_bits.h"
58 #include "mysql/components/services/log_builtins.h"
59 #include "mysql/plugin.h"
60 #include "mysql/psi/mysql_cond.h"
61 #include "mysql/psi/mysql_mutex.h"
62 #include "mysql/status_var.h"
63 #include "sql/changestreams/apply/replication_thread_status.h"
64 #include "sql/rpl_channel_service_interface.h"
65 #ifdef HAVE_SYS_TIME_H
66 #include <sys/time.h>
67 #endif
68 #include <time.h>
69 #ifdef HAVE_UNISTD_H
70 #include <unistd.h>
71 #endif
72 #include <algorithm>
73 #include <atomic>
74 #include <deque>
75 #include <map>
76 #include <regex>
77 #include <string>
78 #include <utility>
79 #include <vector>
80
81 #include "errmsg.h" // CR_*
82 #include "lex_string.h"
83 #include "libbinlogevents/include/binlog_event.h"
84 #include "libbinlogevents/include/compression/iterator.h"
85 #include "libbinlogevents/include/control_events.h"
86 #include "libbinlogevents/include/debug_vars.h"
87 #include "m_ctype.h"
88 #include "m_string.h"
89 #include "mutex_lock.h" // MUTEX_LOCK
90 #include "my_bitmap.h" // MY_BITMAP
91 #include "my_byteorder.h"
92 #include "my_command.h"
93 #include "my_compiler.h"
94 #include "my_dbug.h"
95 #include "my_dir.h"
96 #include "my_io.h"
97 #include "my_loglevel.h"
98 #include "my_macros.h"
99 #include "my_sys.h"
100 #include "my_systime.h"
101 #include "my_thread_local.h" // thread_local_key_t
102 #include "mysql.h" // MYSQL
103 #include "mysql/psi/mysql_file.h"
104 #include "mysql/psi/mysql_memory.h"
105 #include "mysql/psi/mysql_thread.h"
106 #include "mysql/service_mysql_alloc.h"
107 #include "mysql/thread_type.h"
108 #include "mysql_com.h"
109 #include "mysqld_error.h"
110 #include "pfs_thread_provider.h"
111 #include "prealloced_array.h"
112 #include "sql-common/net_ns.h"
113 #include "sql/auth/auth_acls.h"
114 #include "sql/auth/sql_security_ctx.h"
115 #include "sql/auto_thd.h"
116 #include "sql/binlog.h"
117 #include "sql/binlog_reader.h"
118 #include "sql/clone_handler.h" // is_provisioning
119 #include "sql/current_thd.h"
120 #include "sql/debug_sync.h" // DEBUG_SYNC
121 #include "sql/derror.h" // ER_THD
122 #include "sql/dynamic_ids.h" // Server_ids
123 #include "sql/handler.h"
124 #include "sql/item.h"
125 #include "sql/log.h"
126 #include "sql/log_event.h" // Rotate_log_event
127 #include "sql/mdl.h"
128 #include "sql/mysqld.h" // ER
129 #include "sql/mysqld_thd_manager.h" // Global_THD_manager
130 #include "sql/protocol.h"
131 #include "sql/protocol_classic.h"
132 #include "sql/psi_memory_key.h"
133 #include "sql/query_options.h"
134 #include "sql/rpl_applier_reader.h"
135 #include "sql/rpl_async_conn_failover.h"
136 #include "sql/rpl_async_conn_failover_configuration_propagation.h"
137 #include "sql/rpl_filter.h"
138 #include "sql/rpl_group_replication.h"
139 #include "sql/rpl_gtid.h"
140 #include "sql/rpl_handler.h" // RUN_HOOK
141 #include "sql/rpl_info.h"
142 #include "sql/rpl_info_factory.h" // Rpl_info_factory
143 #include "sql/rpl_info_handler.h"
144 #include "sql/rpl_io_monitor.h"
145 #include "sql/rpl_mi.h"
146 #include "sql/rpl_msr.h" // Multisource_info
147 #include "sql/rpl_mta_submode.h"
148 #include "sql/rpl_replica_commit_order_manager.h" // Commit_order_manager
149 #include "sql/rpl_replica_until_options.h"
150 #include "sql/rpl_reporting.h"
151 #include "sql/rpl_rli.h" // Relay_log_info
152 #include "sql/rpl_rli_pdb.h" // Slave_worker
153 #include "sql/rpl_trx_boundary_parser.h"
154 #include "sql/rpl_utility.h"
155 #include "sql/sql_backup_lock.h" // is_instance_backup_locked
156 #include "sql/sql_class.h" // THD
157 #include "sql/sql_const.h"
158 #include "sql/sql_error.h"
159 #include "sql/sql_lex.h"
160 #include "sql/sql_list.h"
161 #include "sql/sql_parse.h" // execute_init_command
162 #include "sql/sql_plugin.h" // opt_plugin_dir_ptr
163 #include "sql/system_variables.h"
164 #include "sql/table.h"
165 #include "sql/transaction.h" // trans_begin
166 #include "sql/transaction_info.h"
167 #include "sql_common.h" // end_server
168 #include "sql_string.h"
169 #include "typelib.h"
170 #ifndef NDEBUG
171 #include "rpl_debug_points.h"
172 #endif
173
174 struct mysql_cond_t;
175 struct mysql_mutex_t;
176
177 using binary_log::checksum_crc32;
178 using binary_log::Log_event_header;
179 using std::max;
180 using std::min;
181
182 #define FLAGSTR(V, F) ((V) & (F) ? #F " " : "")
183
184 /*
185 a parameter of sql_slave_killed() to defer the killed status
186 */
187 #define SLAVE_WAIT_GROUP_DONE 60
188 bool use_slave_mask = false;
189 MY_BITMAP slave_error_mask;
190 char slave_skip_error_names[SHOW_VAR_FUNC_BUFF_SIZE];
191
192 char *replica_load_tmpdir = nullptr;
193 bool replicate_same_server_id;
194 ulonglong relay_log_space_limit = 0;
195 #ifdef WITH_WSREP
196 Master_info *active_mi = 0;
197 #endif /* WITH_WSREP */
198
199 const char *relay_log_index = nullptr;
200 const char *relay_log_basename = nullptr;
201
202 /*
203 MTS load-ballancing parameter.
204 Max length of one MTS Worker queue. The value also determines the size
205 of Relay_log_info::gaq (see @c slave_start_workers()).
206 It can be set to any value in [1, ULONG_MAX - 1] range.
207 */
208 const ulong mts_slave_worker_queue_len_max = 16384;
209
210 /*
211 Statistics go to the error log every # of seconds when
212 --log_error_verbosity > 2
213 */
214 const long mts_online_stat_period = 60 * 2;
215
216 /*
217 MTS load-ballancing parameter.
218 Time unit in microsecs to sleep by MTS Coordinator to avoid extra thread
219 signalling in the case of Worker queues are close to be filled up.
220 */
221 const ulong mts_coordinator_basic_nap = 5;
222
223 /*
224 MTS load-ballancing parameter.
225 Percent of Worker queue size at which Worker is considered to become
226 hungry.
227
228 C enqueues --+ . underrun level
229 V "
230 +----------+-+------------------+--------------+
231 | empty |.|::::::::::::::::::|xxxxxxxxxxxxxx| ---> Worker dequeues
232 +----------+-+------------------+--------------+
233
234 Like in the above diagram enqueuing to the x-d area would indicate
235 actual underrruning by Worker.
236 */
237 const ulong mts_worker_underrun_level = 10;
238
239 /*
240 When slave thread exits, we need to remember the temporary tables so we
241 can re-use them on slave start.
242
243 TODO: move the vars below under Master_info
244 */
245
246 int disconnect_slave_event_count = 0, abort_slave_event_count = 0;
247
248 static thread_local Master_info *RPL_MASTER_INFO = nullptr;
249
250 /**
251 Encapsulates the messages and thread stages used for a specific call
252 to try_to_reconnect. Different Reconnect_messages objects may be
253 used by the caller of try_to_reconnect in order to make the errors
254 and stages include text that describes the reason for the reconnect.
255 */
256 struct Reconnect_messages {
257 /// Stage used while waiting to reconnect
258 PSI_stage_info &stage_waiting_to_reconnect;
259 /// Error reported in case the thread is killed while waiting
260 std::string error_killed_while_waiting;
261 /// Stage used while reconnecting
262 PSI_stage_info &stage_reconnecting;
263 /// Description of the condition that caused the thread to reconnect
264 std::string triggering_error;
265 /**
266 The string representation of the enum_server_command that had been
267 sent to the source before condition that caused the thread to
268 reconnect happened.
269 */
270 std::string triggering_command;
271 };
272
273 static Reconnect_messages reconnect_messages_after_failed_registration{
274 stage_replica_waiting_to_reconnect_after_failed_registration_on_source,
275 "Slave I/O thread killed while waiting to reconnect after a failed "
276 "registration on master",
277 stage_replica_reconnecting_after_failed_registration_on_source,
278 "failed registering on master, reconnecting to try again, "
279 "log '%s' at position %s",
280 "COM_REGISTER_SLAVE"};
281
282 static Reconnect_messages reconnect_messages_after_failed_dump{
283 stage_replica_waiting_to_reconnect_after_failed_binlog_dump_request,
284 "Slave I/O thread killed while retrying master dump",
285 stage_replica_reconnecting_after_failed_binlog_dump_request,
286 "failed dump request, reconnecting to try again, log '%s' at position "
287 "%s",
288 "COM_BINLOG_DUMP"};
289
290 static Reconnect_messages reconnect_messages_after_failed_event_read{
291 stage_replica_waiting_to_reconnect_after_failed_event_read,
292 "Slave I/O thread killed while waiting to reconnect after a failed read",
293 stage_replica_reconnecting_after_failed_event_read,
294 "Slave I/O thread: Failed reading log event, reconnecting to retry, "
295 "log '%s' at position %s",
296 ""};
297
298 enum enum_slave_apply_event_and_update_pos_retval {
299 SLAVE_APPLY_EVENT_AND_UPDATE_POS_OK = 0,
300 SLAVE_APPLY_EVENT_AND_UPDATE_POS_APPLY_ERROR = 1,
301 SLAVE_APPLY_EVENT_AND_UPDATE_POS_UPDATE_POS_ERROR = 2,
302 SLAVE_APPLY_EVENT_AND_UPDATE_POS_APPEND_JOB_ERROR = 3,
303 SLAVE_APPLY_EVENT_RETRY = 4,
304 SLAVE_APPLY_EVENT_UNTIL_REACHED = 5,
305 SLAVE_APPLY_EVENT_AND_UPDATE_POS_MAX
306 };
307
308 static int process_io_rotate(Master_info *mi, Rotate_log_event *rev);
309 static bool wait_for_relay_log_space(Relay_log_info *rli);
310 static inline bool io_slave_killed(THD *thd, Master_info *mi);
311 static inline bool monitor_io_replica_killed(THD *thd, Master_info *mi);
312 static inline bool is_autocommit_off_and_infotables(THD *thd);
313 static void print_replica_skip_errors(void);
314 static int safe_connect(THD *thd, MYSQL *mysql, Master_info *mi,
315 const std::string &host = std::string(),
316 const uint port = 0);
317 static int safe_reconnect(THD *thd, MYSQL *mysql, Master_info *mi,
318 bool suppress_warnings,
319 const std::string &host = std::string(),
320 const uint port = 0);
321 static int get_master_version_and_clock(MYSQL *mysql, Master_info *mi);
322 static int get_master_uuid(MYSQL *mysql, Master_info *mi);
323 int io_thread_init_commands(MYSQL *mysql, Master_info *mi);
324 static int terminate_slave_thread(THD *thd, mysql_mutex_t *term_lock,
325 mysql_cond_t *term_cond,
326 std::atomic<uint> *slave_running,
327 ulong *stop_wait_timeout, bool need_lock_term,
328 bool force = false);
329 static bool check_io_slave_killed(THD *thd, Master_info *mi, const char *info);
330 static int mts_event_coord_cmp(LOG_POS_COORD *id1, LOG_POS_COORD *id2);
331
332 static int check_slave_sql_config_conflict(const Relay_log_info *rli);
333 static void group_replication_cleanup_after_clone();
334
335 static void check_replica_configuration_restrictions();
336 static bool check_replica_configuration_errors(Master_info *mi,
337 int thread_mask);
338 /*
339 Applier thread InnoDB priority.
340 When two transactions conflict inside InnoDB, the one with
341 greater priority wins.
342
343 @param thd Thread handler for slave
344 @param priority Thread priority
345 */
346 49813 static void set_thd_tx_priority(THD *thd, int priority) {
347
1/2
✓ Branch 0 taken 49813 times.
✗ Branch 1 not taken.
49813 DBUG_TRACE;
348
3/4
✓ Branch 0 taken 39763 times.
✓ Branch 1 taken 10050 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 39763 times.
49813 assert(thd->system_thread == SYSTEM_THREAD_SLAVE_SQL ||
349 thd->system_thread == SYSTEM_THREAD_SLAVE_WORKER);
350
351 #ifdef WITH_WSREP
352
2/2
✓ Branch 0 taken 11566 times.
✓ Branch 1 taken 38247 times.
49813 if (priority > 0)
353
10/22
✓ Branch 0 taken 11566 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11566 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11566 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 11566 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 11566 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 11566 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 11566 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 11566 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 11566 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✓ Branch 19 taken 11566 times.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
11566 WSREP_WARN("InnoDB High Priority being used for slave: %d -> %d",
354 thd->thd_tx_priority, priority);
355 #endif /* WITH_WSREP */
356 49813 thd->thd_tx_priority = priority;
357
3/4
✓ Branch 0 taken 49813 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 49803 times.
49813 DBUG_EXECUTE_IF("dbug_set_high_prio_sql_thread",
358 { thd->thd_tx_priority = 1; });
359 49813 }
360
361 /**
362 Set for the thread options about the memory and size limits when
363 transactions collect write sets.
364
365 @param thd Thread handler
366 @param ignore_limit if the memory limits should be ignored
367 @param allow_drop_write_set if this thread does not require WS to always be
368 logged
369 */
370 49813 static void set_thd_write_set_options(THD *thd, bool ignore_limit,
371 bool allow_drop_write_set) {
372
1/2
✓ Branch 0 taken 49813 times.
✗ Branch 1 not taken.
49813 DBUG_TRACE;
373 thd->get_transaction()
374 ->get_transaction_write_set_ctx()
375
1/2
✓ Branch 0 taken 49813 times.
✗ Branch 1 not taken.
49813 ->set_local_ignore_write_set_memory_limit(ignore_limit);
376 thd->get_transaction()
377 ->get_transaction_write_set_ctx()
378
1/2
✓ Branch 0 taken 49813 times.
✗ Branch 1 not taken.
49813 ->set_local_allow_drop_write_set(allow_drop_write_set);
379 49813 }
380
381 /*
382 Function to set the slave's max_allowed_packet based on the value
383 of replica_max_allowed_packet.
384
385 @in_param thd Thread handler for slave
386 @in_param mysql MySQL connection handle
387 */
388
389 7731 static void set_replica_max_allowed_packet(THD *thd, MYSQL *mysql) {
390
1/2
✓ Branch 0 taken 7731 times.
✗ Branch 1 not taken.
7731 DBUG_TRACE;
391 // thd and mysql must be valid
392
2/4
✓ Branch 0 taken 7731 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7731 times.
✗ Branch 3 not taken.
7731 assert(thd && mysql);
393
394 7731 thd->variables.max_allowed_packet = replica_max_allowed_packet;
395 /*
396 Adding MAX_LOG_EVENT_HEADER_LEN to the max_packet_size on the I/O
397 thread and the mysql->option max_allowed_packet, since a
398 replication event can become this much larger than
399 the corresponding packet (query) sent from client to master.
400 */
401
2/4
✓ Branch 0 taken 7731 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7731 times.
✗ Branch 3 not taken.
7731 thd->get_protocol_classic()->set_max_packet_size(replica_max_allowed_packet +
402 MAX_LOG_EVENT_HEADER);
403 /*
404 Skipping the setting of mysql->net.max_packet size to slave
405 max_allowed_packet since this is done during mysql_real_connect.
406 */
407 7731 mysql->options.max_allowed_packet =
408 7731 replica_max_allowed_packet + MAX_LOG_EVENT_HEADER;
409 7731 }
410
411 #ifdef HAVE_PSI_INTERFACE
412
413 static PSI_memory_key key_memory_rli_mta_coor;
414
415 static PSI_thread_key key_thread_replica_io, key_thread_replica_sql,
416 key_thread_replica_worker, key_thread_replica_monitor_io;
417
418 static PSI_thread_info all_slave_threads[] = {
419 {&key_thread_replica_io, "replica_io", "rpl_rca_io", PSI_FLAG_THREAD_SYSTEM,
420 0, PSI_DOCUMENT_ME},
421 {&key_thread_replica_sql, "replica_sql", "rpl_rca_sql",
422 PSI_FLAG_THREAD_SYSTEM, 0, PSI_DOCUMENT_ME},
423 {&key_thread_replica_worker, "replica_worker", "rpl_rca_wkr",
424 PSI_FLAG_THREAD_SYSTEM, 0, PSI_DOCUMENT_ME},
425 {&key_thread_replica_monitor_io, "replica_monitor", "rpl_rca_mon",
426 PSI_FLAG_SINGLETON | PSI_FLAG_THREAD_SYSTEM, 0, PSI_DOCUMENT_ME}};
427
428 static PSI_memory_info all_slave_memory[] = {{&key_memory_rli_mta_coor,
429 "Relay_log_info::mta_coor", 0, 0,
430 PSI_DOCUMENT_ME}};
431
432 9173 static void init_replica_psi_keys(void) {
433 9173 const char *category = "sql";
434 int count;
435
436 9173 count = static_cast<int>(array_elements(all_slave_threads));
437 9173 mysql_thread_register(category, all_slave_threads, count);
438
439 9173 count = static_cast<int>(array_elements(all_slave_memory));
440 9173 mysql_memory_register(category, all_slave_memory, count);
441 9173 }
442 #endif /* HAVE_PSI_INTERFACE */
443
444 /* Initialize slave structures */
445
446 9173 int init_replica() {
447
1/2
✓ Branch 0 taken 9173 times.
✗ Branch 1 not taken.
9173 DBUG_TRACE;
448 9173 int error = 0;
449 9173 int thread_mask = SLAVE_SQL | SLAVE_IO;
450
451 #ifdef HAVE_PSI_INTERFACE
452
1/2
✓ Branch 0 taken 9173 times.
✗ Branch 1 not taken.
9173 init_replica_psi_keys();
453 #endif
454
455 /*
456 This is called when mysqld starts. Before client connections are
457 accepted. However bootstrap may conflict with us if it does START SLAVE.
458 So it's safer to take the lock.
459 */
460
1/2
✓ Branch 0 taken 9173 times.
✗ Branch 1 not taken.
9173 channel_map.wrlock();
461
462 9173 RPL_MASTER_INFO = nullptr;
463
464 /*
465 Create slave info objects by reading repositories of individual
466 channels and add them into channel_map
467 */
468
3/4
✓ Branch 0 taken 9173 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 9162 times.
9173 if ((error = Rpl_info_factory::create_slave_info_objects(
469 opt_mi_repository_id, opt_rli_repository_id, thread_mask,
470 &channel_map)))
471
8/16
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 11 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 11 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 11 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 11 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 11 times.
✗ Branch 15 not taken.
11 LogErr(ERROR_LEVEL,
472 ER_RPL_SLAVE_FAILED_TO_CREATE_OR_RECOVER_INFO_REPOSITORIES);
473
474
1/2
✓ Branch 0 taken 9173 times.
✗ Branch 1 not taken.
9173 group_replication_cleanup_after_clone();
475
476 #ifdef WITH_WSREP
477 /*
478 for only wsrep, create active_mi, for async slave restart purpose
479 */
480
1/2
✓ Branch 0 taken 9173 times.
✗ Branch 1 not taken.
9173 active_mi = channel_map.get_default_channel_mi();
481 #endif /* WITH_WSREP */
482
483 #ifndef NDEBUG
484 /* @todo: Print it for all the channels */
485 {
486 Master_info *default_mi;
487
1/2
✓ Branch 0 taken 9173 times.
✗ Branch 1 not taken.
9173 default_mi = channel_map.get_default_channel_mi();
488
3/4
✓ Branch 0 taken 9168 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 9168 times.
✗ Branch 3 not taken.
9173 if (default_mi && default_mi->rli) {
489
3/8
✓ Branch 0 taken 9168 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9168 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 9168 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
9168 DBUG_PRINT("info",
490 ("init group master %s %lu group relay %s %lu event %s %lu\n",
491 default_mi->rli->get_group_master_log_name(),
492 (ulong)default_mi->rli->get_group_master_log_pos(),
493 default_mi->rli->get_group_relay_log_name(),
494 (ulong)default_mi->rli->get_group_relay_log_pos(),
495 default_mi->rli->get_event_relay_log_name(),
496 (ulong)default_mi->rli->get_event_relay_log_pos()));
497 }
498 }
499 #endif
500
501
1/2
✓ Branch 0 taken 9173 times.
✗ Branch 1 not taken.
9173 check_replica_configuration_restrictions();
502
503
2/4
✓ Branch 0 taken 9173 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9173 times.
9173 if (check_slave_sql_config_conflict(nullptr)) {
504 error = 1;
505 goto err;
506 }
507
508 /*
509 Loop through the channel_map and start slave threads for each channel.
510 */
511
2/2
✓ Branch 0 taken 3254 times.
✓ Branch 1 taken 5919 times.
9173 if (!opt_skip_replica_start) {
512
4/6
✓ Branch 0 taken 5919 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11863 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5944 times.
✓ Branch 5 taken 5919 times.
11863 for (mi_map::iterator it = channel_map.begin(); it != channel_map.end();
513 5944 it++) {
514 5944 Master_info *mi = it->second;
515
516 /* If server id is not set, start_slave_thread() will say it */
517
6/6
✓ Branch 0 taken 90 times.
✓ Branch 1 taken 5854 times.
✓ Branch 2 taken 84 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 84 times.
✓ Branch 5 taken 5860 times.
5944 if (Master_info::is_configured(mi) && mi->rli->inited) {
518 /* same as in start_slave() cache the global var values into rli's
519 * members */
520 84 mi->rli->opt_replica_parallel_workers =
521 opt_mts_replica_parallel_workers;
522 84 mi->rli->checkpoint_group = opt_mta_checkpoint_group;
523
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 84 times.
84 if (mts_parallel_option == MTS_PARALLEL_TYPE_DB_NAME)
524 mi->rli->channel_mts_submode = MTS_PARALLEL_TYPE_DB_NAME;
525 else
526 84 mi->rli->channel_mts_submode = MTS_PARALLEL_TYPE_LOGICAL_CLOCK;
527
528
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 83 times.
84 if (mi->is_source_connection_auto_failover())
529 1 thread_mask |= SLAVE_MONITOR;
530
531
2/4
✓ Branch 0 taken 84 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 84 times.
84 if (start_slave_threads(true /*need_lock_slave=true*/,
532 false /*wait_for_start=false*/, mi,
533 thread_mask)) {
534 LogErr(ERROR_LEVEL, ER_FAILED_TO_START_SLAVE_THREAD,
535 mi->get_channel());
536 }
537 } else {
538
8/16
✓ Branch 0 taken 5860 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5860 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5860 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5860 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5860 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 5860 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 5860 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 5860 times.
✗ Branch 15 not taken.
5860 LogErr(INFORMATION_LEVEL, ER_FAILED_TO_START_SLAVE_THREAD,
539 mi->get_channel());
540 }
541 }
542 }
543
544 3254 err:
545
546
1/2
✓ Branch 0 taken 9173 times.
✗ Branch 1 not taken.
9173 channel_map.unlock();
547
10/18
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 9162 times.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 11 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 11 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 11 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 11 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 11 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 11 times.
✗ Branch 17 not taken.
9173 if (error) LogErr(INFORMATION_LEVEL, ER_SLAVE_NOT_STARTED_ON_SOME_CHANNELS);
548
549 9173 return error;
550 9173 }
551
552 /**
553 Function to start a slave for all channels.
554 Used in Multisource replication.
555 @param[in] thd THD object of the client.
556
557 @retval false success
558 @retval true error
559
560 @todo It is good to continue to start other channels
561 when a slave start failed for other channels.
562
563 @todo The problem with the below code is if the slave is already
564 stared, we would have multiple warnings
565 "Slave was already running" for each channel.
566 A nice warning message would be to add
567 "Slave for channel '%s' was already running"
568 but error messages are in different languages and cannot be tampered
569 with so, we have to handle it case by case basis, whether
570 only default channel exists or not and properly continue with
571 starting other channels if one channel fails clearly giving
572 an error message by displaying failed channels.
573 */
574 6655 bool start_slave(THD *thd) {
575
1/2
✓ Branch 0 taken 6655 times.
✗ Branch 1 not taken.
6655 DBUG_TRACE;
576 Master_info *mi;
577 6655 bool channel_configured, error = false;
578
579
3/4
✓ Branch 0 taken 6655 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6561 times.
✓ Branch 3 taken 94 times.
6655 if (channel_map.get_num_instances() == 1) {
580
1/2
✓ Branch 0 taken 6561 times.
✗ Branch 1 not taken.
6561 mi = channel_map.get_default_channel_mi();
581
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6561 times.
6561 assert(mi);
582
2/2
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 6516 times.
6555 if (start_slave(thd, &thd->lex->slave_connection, &thd->lex->mi,
583
1/2
✓ Branch 0 taken 6555 times.
✗ Branch 1 not taken.
6561 thd->lex->slave_thd_opt, mi, true))
584 39 return true;
585 } else {
586 /*
587 Users cannot start more than one channel's applier thread
588 if sql_replica_skip_counter > 0. It throws an error to the session.
589 */
590
1/2
✓ Branch 0 taken 94 times.
✗ Branch 1 not taken.
94 mysql_mutex_lock(&LOCK_sql_replica_skip_counter);
591 /* sql_replica_skip_counter > 0 && !(START SLAVE IO_THREAD) */
592
4/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 91 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1 times.
94 if (sql_replica_skip_counter > 0 && !(thd->lex->slave_thd_opt & SLAVE_IO)) {
593
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_error(ER_SLAVE_CHANNEL_SQL_SKIP_COUNTER, MYF(0));
594
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 mysql_mutex_unlock(&LOCK_sql_replica_skip_counter);
595 2 return true;
596 }
597
1/2
✓ Branch 0 taken 92 times.
✗ Branch 1 not taken.
92 mysql_mutex_unlock(&LOCK_sql_replica_skip_counter);
598
599
4/6
✓ Branch 0 taken 92 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 353 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 261 times.
✓ Branch 5 taken 92 times.
353 for (mi_map::iterator it = channel_map.begin(); it != channel_map.end();
600 261 it++) {
601 261 mi = it->second;
602
603 261 channel_configured =
604 261 mi && // Master_info exists
605
3/4
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 189 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 72 times.
261 (mi->inited || mi->reset) // It is inited or was reset
606
2/4
✓ Branch 0 taken 261 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 189 times.
✗ Branch 3 not taken.
522 && mi->host[0]; // host is set
607
608
2/2
✓ Branch 0 taken 189 times.
✓ Branch 1 taken 72 times.
261 if (channel_configured) {
609
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 186 times.
189 if (start_slave(thd, &thd->lex->slave_connection, &thd->lex->mi,
610
1/2
✓ Branch 0 taken 189 times.
✗ Branch 1 not taken.
189 thd->lex->slave_thd_opt, mi, true)) {
611
8/16
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 3 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 3 times.
✗ Branch 15 not taken.
3 LogErr(ERROR_LEVEL, ER_RPL_SLAVE_CANT_START_SLAVE_FOR_CHANNEL,
612 mi->get_channel());
613 3 error = true;
614 }
615 }
616 }
617 }
618
2/2
✓ Branch 0 taken 6605 times.
✓ Branch 1 taken 3 times.
6608 if (!error) {
619 /* no error */
620
1/2
✓ Branch 0 taken 6605 times.
✗ Branch 1 not taken.
6605 my_ok(thd);
621 }
622 6608 return error;
623 6649 }
624
625 /**
626 Function to stop a slave for all channels.
627 Used in Multisource replication.
628 @param[in] thd THD object of the client.
629
630 @retval 0 success
631 @retval 1 error
632
633 @todo It is good to continue to stop other channels
634 when a slave start failed for other channels.
635 */
636 5427 int stop_slave(THD *thd) {
637
1/2
✓ Branch 0 taken 5427 times.
✗ Branch 1 not taken.
5427 DBUG_TRACE;
638 5427 bool push_temp_table_warning = true;
639 5427 Master_info *mi = nullptr;
640 5427 int error = 0;
641
642
3/4
✓ Branch 0 taken 5427 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5359 times.
✓ Branch 3 taken 68 times.
5427 if (channel_map.get_num_instances() == 1) {
643
1/2
✓ Branch 0 taken 5359 times.
✗ Branch 1 not taken.
5359 mi = channel_map.get_default_channel_mi();
644
645
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5359 times.
5359 assert(!strcmp(mi->get_channel(), channel_map.get_default_channel()));
646
647
1/2
✓ Branch 0 taken 5359 times.
✗ Branch 1 not taken.
5359 error = stop_slave(thd, mi, true, false /*for_one_channel*/,
648 &push_temp_table_warning);
649 } else {
650
4/6
✓ Branch 0 taken 68 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 300 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 232 times.
✓ Branch 5 taken 68 times.
300 for (mi_map::iterator it = channel_map.begin(); it != channel_map.end();
651 232 it++) {
652 232 mi = it->second;
653
654
2/2
✓ Branch 0 taken 177 times.
✓ Branch 1 taken 55 times.
232 if (Master_info::is_configured(mi)) {
655
2/4
✓ Branch 0 taken 177 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 177 times.
177 if (stop_slave(thd, mi, true, false /*for_one_channel*/,
656 &push_temp_table_warning)) {
657 LogErr(ERROR_LEVEL, ER_RPL_SLAVE_CANT_STOP_SLAVE_FOR_CHANNEL,
658 mi->get_channel());
659 error = 1;
660 }
661 }
662 }
663 }
664
665
2/2
✓ Branch 0 taken 5426 times.
✓ Branch 1 taken 1 times.
5427 if (!error) {
666 /* no error */
667
1/2
✓ Branch 0 taken 5426 times.
✗ Branch 1 not taken.
5426 my_ok(thd);
668 }
669
670 5427 return error;
671 5427 }
672
673 /**
674 Entry point to the START SLAVE command. The function
675 decides to start replication threads on several channels
676 or a single given channel.
677
678 @param[in] thd the client thread carrying the command.
679
680 @retval false ok
681 @retval true not ok.
682 */
683 7030 bool start_slave_cmd(THD *thd) {
684
1/2
✓ Branch 0 taken 7030 times.
✗ Branch 1 not taken.
7030 DBUG_TRACE;
685
686 Master_info *mi;
687 7030 LEX *lex = thd->lex;
688 7030 bool res = true; /* default, an error */
689
690
2/4
✓ Branch 0 taken 7030 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7030 times.
✗ Branch 3 not taken.
7030 DEBUG_SYNC(thd, "begin_start_replica");
691
692
1/2
✓ Branch 0 taken 7030 times.
✗ Branch 1 not taken.
7030 channel_map.wrlock();
693
694
2/4
✓ Branch 0 taken 7030 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7030 times.
✗ Branch 3 not taken.
7030 DEBUG_SYNC(thd, "after_locking_channel_map_in_start_replica");
695
696
3/4
✓ Branch 0 taken 7030 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 7024 times.
7030 if (!is_slave_configured()) {
697
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 my_error(ER_SLAVE_CONFIGURATION, MYF(0));
698 6 goto err;
699 }
700 #ifdef WITH_WSREP
701
5/6
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 7005 times.
✓ Branch 2 taken 19 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 18 times.
7024 if (WSREP_ON && !opt_log_replica_updates) {
702 /*
703 bad configuration, mysql replication would not be forwarded to wsrep
704 cluster which would lead to immediate inconsistency
705 */
706
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_message(ER_SLAVE_CONFIGURATION,
707 "bad configuration no log_slave_updates"
708 " defined, slave would not replicate further to wsrep cluster",
709 MYF(0));
710 1 goto err;
711 }
712 #endif /* WITH_WSREP */
713
714
2/2
✓ Branch 0 taken 6657 times.
✓ Branch 1 taken 366 times.
7023 if (!lex->mi.for_channel) {
715 /*
716 If slave_until options are provided when multiple channels exist
717 without explicitly providing FOR CHANNEL clause, error out.
718 */
719
7/8
✓ Branch 0 taken 119 times.
✓ Branch 1 taken 6538 times.
✓ Branch 2 taken 119 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 117 times.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 6655 times.
6657 if (lex->mi.slave_until && channel_map.get_num_instances() > 1) {
720
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_error(ER_SLAVE_MULTIPLE_CHANNELS_CMD, MYF(0));
721 2 goto err;
722 }
723
724
1/2
✓ Branch 0 taken 6649 times.
✗ Branch 1 not taken.
6655 res = start_slave(thd);
725 #ifdef WITH_WSREP
726 // Similar to GR, do not allow operations on the wsrep channel
727
6/8
✓ Branch 0 taken 366 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 366 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 364 times.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 364 times.
366 } else if (lex->mi.channel && wsrep_is_wsrep_channel_name(lex->mi.channel)) {
728 2 const char *command = "START SLAVE FOR CHANNEL";
729
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (thd->lex->slave_thd_opt & SLAVE_IO)
730 command = "START SLAVE IO_THREAD FOR CHANNEL";
731
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 else if (thd->lex->slave_thd_opt & SLAVE_SQL)
732 command = "START SLAVE SQL_THREAD FOR CHANNEL";
733
734
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_error(ER_SLAVE_CHANNEL_OPERATION_NOT_ALLOWED, MYF(0), command,
735 lex->mi.channel, command);
736
737 2 goto err;
738 #endif /* WITH_WSREP */
739 } else {
740
1/2
✓ Branch 0 taken 364 times.
✗ Branch 1 not taken.
364 mi = channel_map.get_mi(lex->mi.channel);
741
742 /*
743 If the channel being used is a group replication channel we need to
744 disable this command here as, in some cases, group replication does not
745 support them.
746
747 For channel group_replication_applier we disable START SLAVE [IO_THREAD]
748 command.
749
750 For channel group_replication_recovery we disable START SLAVE command
751 and its two thread variants.
752 */
753 723 if (mi &&
754
7/8
✓ Branch 0 taken 359 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 359 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 68 times.
✓ Branch 5 taken 291 times.
✓ Branch 6 taken 17 times.
✓ Branch 7 taken 347 times.
432 channel_map.is_group_replication_channel_name(mi->get_channel()) &&
755
4/4
✓ Branch 0 taken 63 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 56 times.
✓ Branch 3 taken 7 times.
68 ((!thd->lex->slave_thd_opt || (thd->lex->slave_thd_opt & SLAVE_IO)) ||
756
3/4
✓ Branch 0 taken 56 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 51 times.
56 (!(channel_map.is_group_replication_channel_name(mi->get_channel(),
757 5 true)) &&
758
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 (thd->lex->slave_thd_opt & SLAVE_SQL)))) {
759 17 const char *command = "START SLAVE FOR CHANNEL";
760
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 10 times.
17 if (thd->lex->slave_thd_opt & SLAVE_IO)
761 7 command = "START SLAVE IO_THREAD FOR CHANNEL";
762
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
10 else if (thd->lex->slave_thd_opt & SLAVE_SQL)
763 5 command = "START SLAVE SQL_THREAD FOR CHANNEL";
764
765
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 my_error(ER_SLAVE_CHANNEL_OPERATION_NOT_ALLOWED, MYF(0), command,
766 mi->get_channel(), command);
767
768 17 goto err;
769 }
770
771
2/2
✓ Branch 0 taken 342 times.
✓ Branch 1 taken 5 times.
347 if (mi)
772 342 res = start_slave(thd, &thd->lex->slave_connection, &thd->lex->mi,
773
1/2
✓ Branch 0 taken 342 times.
✗ Branch 1 not taken.
342 thd->lex->slave_thd_opt, mi, true);
774
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 else if (strcmp(channel_map.get_default_channel(), lex->mi.channel))
775
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 my_error(ER_SLAVE_CHANNEL_DOES_NOT_EXIST, MYF(0), lex->mi.channel);
776
777
3/4
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 338 times.
✓ Branch 2 taken 338 times.
✗ Branch 3 not taken.
347 if (!res) my_ok(thd);
778 }
779 9 err:
780
1/2
✓ Branch 0 taken 7024 times.
✗ Branch 1 not taken.
7024 channel_map.unlock();
781 7024 return res;
782 7024 }
783
784 /**
785 Entry point for the STOP SLAVE command. This function stops replication
786 threads for all channels or a single channel based on the command
787 options supplied.
788
789 @param[in] thd the client thread.
790
791 @retval false ok
792 @retval true not ok.
793 */
794 5878 bool stop_slave_cmd(THD *thd) {
795
1/2
✓ Branch 0 taken 5878 times.
✗ Branch 1 not taken.
5878 DBUG_TRACE;
796
797 Master_info *mi;
798 5878 bool push_temp_table_warning = true;
799 5878 LEX *lex = thd->lex;
800 5878 bool res = true; /*default, an error */
801
802
1/2
✓ Branch 0 taken 5878 times.
✗ Branch 1 not taken.
5878 channel_map.rdlock();
803
804
3/4
✓ Branch 0 taken 5878 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 5877 times.
5878 if (!is_slave_configured()) {
805
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_SLAVE_CONFIGURATION, MYF(0));
806
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 channel_map.unlock();
807 1 return true;
808 }
809
810
1/2
✓ Branch 0 taken 5877 times.
✗ Branch 1 not taken.
5877 MDL_lock_guard backup_sentry{thd};
811 /* During provisioning we stop slave after acquiring backup lock. */
812
4/4
✓ Branch 0 taken 5820 times.
✓ Branch 1 taken 57 times.
✓ Branch 2 taken 5244 times.
✓ Branch 3 taken 633 times.
11697 if (!Clone_handler::is_provisioning() &&
813
4/4
✓ Branch 0 taken 1289 times.
✓ Branch 1 taken 4531 times.
✓ Branch 2 taken 713 times.
✓ Branch 3 taken 576 times.
5820 (!thd->lex->slave_thd_opt || (thd->lex->slave_thd_opt & SLAVE_SQL))) {
814
3/4
✓ Branch 0 taken 5244 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 5239 times.
5244 if (backup_sentry.lock(MDL_key::BACKUP_LOCK, MDL_INTENTION_EXCLUSIVE)) {
815
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 my_error(ER_RPL_CANT_STOP_SLAVE_WHILE_LOCKED_BACKUP, MYF(0));
816
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 channel_map.unlock();
817 5 return true;
818 }
819 }
820
821
3/4
✓ Branch 0 taken 5427 times.
✓ Branch 1 taken 445 times.
✓ Branch 2 taken 5427 times.
✗ Branch 3 not taken.
5872 if (!lex->mi.for_channel) res = stop_slave(thd);
822 #ifdef WITH_WSREP
823 // Similar to GR, do not allow operations on the wsrep channel
824
6/8
✓ Branch 0 taken 445 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 445 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 443 times.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 443 times.
445 else if (lex->mi.channel && wsrep_is_wsrep_channel_name(lex->mi.channel)) {
825 2 const char *command = "STOP SLAVE FOR CHANNEL";
826
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (thd->lex->slave_thd_opt & SLAVE_IO)
827 command = "STOP SLAVE IO_THREAD FOR CHANNEL";
828
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 else if (thd->lex->slave_thd_opt & SLAVE_SQL)
829 command = "STOP SLAVE SQL_THREAD FOR CHANNEL";
830
831
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_error(ER_SLAVE_CHANNEL_OPERATION_NOT_ALLOWED, MYF(0), command,
832 lex->mi.channel, command);
833
834
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 channel_map.unlock();
835 2 return true;
836 }
837 #endif /* WITH_WSREP */
838 else {
839
1/2
✓ Branch 0 taken 443 times.
✗ Branch 1 not taken.
443 mi = channel_map.get_mi(lex->mi.channel);
840
841 /*
842 If the channel being used is a group replication channel we need to
843 disable this command here as, in some cases, group replication does not
844 support them.
845
846 For channel group_replication_applier we disable STOP SLAVE [IO_THREAD]
847 command.
848
849 For channel group_replication_recovery we disable STOP SLAVE command
850 and its two thread variants.
851 */
852 882 if (mi &&
853
7/8
✓ Branch 0 taken 439 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 439 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 92 times.
✓ Branch 5 taken 347 times.
✓ Branch 6 taken 13 times.
✓ Branch 7 taken 430 times.
535 channel_map.is_group_replication_channel_name(mi->get_channel()) &&
854
4/4
✓ Branch 0 taken 87 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 82 times.
✓ Branch 3 taken 5 times.
92 ((!thd->lex->slave_thd_opt || (thd->lex->slave_thd_opt & SLAVE_IO)) ||
855
3/4
✓ Branch 0 taken 82 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 79 times.
82 (!(channel_map.is_group_replication_channel_name(mi->get_channel(),
856 3 true)) &&
857
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 (thd->lex->slave_thd_opt & SLAVE_SQL)))) {
858 13 const char *command = "STOP SLAVE FOR CHANNEL";
859
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 8 times.
13 if (thd->lex->slave_thd_opt & SLAVE_IO)
860 5 command = "STOP SLAVE IO_THREAD FOR CHANNEL";
861
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 5 times.
8 else if (thd->lex->slave_thd_opt & SLAVE_SQL)
862 3 command = "STOP SLAVE SQL_THREAD FOR CHANNEL";
863
864
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 my_error(ER_SLAVE_CHANNEL_OPERATION_NOT_ALLOWED, MYF(0), command,
865 mi->get_channel(), command);
866
867
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 channel_map.unlock();
868 13 return true;
869 }
870
871
2/2
✓ Branch 0 taken 426 times.
✓ Branch 1 taken 4 times.
430 if (mi)
872
1/2
✓ Branch 0 taken 426 times.
✗ Branch 1 not taken.
426 res = stop_slave(thd, mi, true /*net report */, true /*for_one_channel*/,
873 &push_temp_table_warning);
874
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 else if (strcmp(channel_map.get_default_channel(), lex->mi.channel))
875
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 my_error(ER_SLAVE_CHANNEL_DOES_NOT_EXIST, MYF(0), lex->mi.channel);
876 }
877
878
1/2
✓ Branch 0 taken 5857 times.
✗ Branch 1 not taken.
5857 channel_map.unlock();
879
880
4/6
✓ Branch 0 taken 5857 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 5855 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
5857 DBUG_EXECUTE_IF("stop_replica_dont_release_backup_lock", {
881 rpl_replica_debug_point(DBUG_RPL_S_STOP_SLAVE_BACKUP_LOCK, thd);
882 });
883
884 5857 return res;
885 5878 }
886
887 enum enum_read_rotate_from_relay_log_status {
888 FOUND_ROTATE,
889 NOT_FOUND_ROTATE,
890 ERROR
891 };
892
893 /**
894 Parse the given relay log and identify the rotate event from the master.
895 Ignore the Format description event, Previous_gtid log event, ignorable
896 event and Stop event within the relay log as they are generated by slave.
897 When a rotate event is found check if it is a rotate that is originated from
898 the master based on the server_id. Ignore the event if the rotate is from
899 slave or if it is a fake rotate event. If any other events are encountered
900 apart from the above events generate an error. From the rotate event
901 extract the master's binary log name and position.
902
903 @param filename
904 Relay log name which needs to be parsed.
905
906 @param[out] master_log_file
907 Set the master_log_file to the log file name that is extracted from
908 rotate event. The master_log_file should contain string of len
909 FN_REFLEN.
910
911 @param[out] master_log_pos
912 Set the master_log_pos to the log position extracted from rotate
913 event.
914
915 @retval FOUND_ROTATE: When rotate event is found in the relay log
916 @retval NOT_FOUND_ROTATE: When rotate event is not found in the relay log
917 @retval ERROR: On error
918 */
919 17 static enum_read_rotate_from_relay_log_status read_rotate_from_relay_log(
920 char *filename, char *master_log_file, my_off_t *master_log_pos) {
921
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 DBUG_TRACE;
922
923
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 Relaylog_file_reader relaylog_file_reader(opt_replica_sql_verify_checksum);
924
2/4
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 17 times.
17 if (relaylog_file_reader.open(filename)) {
925 LogErr(ERROR_LEVEL, ER_RPL_RECOVERY_ERROR,
926 relaylog_file_reader.get_error_str());
927 return ERROR;
928 }
929
930 17 Log_event *ev = nullptr;
931 17 bool done = false;
932 17 enum_read_rotate_from_relay_log_status ret = NOT_FOUND_ROTATE;
933
7/8
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 60 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 47 times.
✓ Branch 5 taken 13 times.
✓ Branch 6 taken 47 times.
✓ Branch 7 taken 17 times.
64 while (!done && (ev = relaylog_file_reader.read_event_object()) != nullptr) {
934
3/10
✓ Branch 0 taken 47 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 47 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 47 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
47 DBUG_PRINT("info", ("Read event of type %s", ev->get_type_str()));
935
4/6
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
47 switch (ev->get_type_code()) {
936 17 case binary_log::FORMAT_DESCRIPTION_EVENT:
937 case binary_log::START_5_7_ENCRYPTION_EVENT:
938 17 break;
939 8 case binary_log::ROTATE_EVENT:
940 /*
941 Check for rotate event from the master. Ignore the ROTATE event if it
942 is a fake rotate event with server_id=0.
943 */
944
3/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 4 times.
8 if (ev->server_id && ev->server_id != ::server_id) {
945
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 Rotate_log_event *rotate_ev = (Rotate_log_event *)ev;
946
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 assert(FN_REFLEN >= rotate_ev->ident_len + 1);
947 4 memcpy(master_log_file, rotate_ev->new_log_ident,
948 4 rotate_ev->ident_len + 1);
949 4 *master_log_pos = rotate_ev->pos;
950 4 ret = FOUND_ROTATE;
951 4 done = true;
952 }
953 8 break;
954 17 case binary_log::PREVIOUS_GTIDS_LOG_EVENT:
955 17 break;
956 case binary_log::IGNORABLE_LOG_EVENT:
957 break;
958 5 case binary_log::STOP_EVENT:
959 5 break;
960 default:
961 LogErr(ERROR_LEVEL, ER_RPL_RECOVERY_NO_ROTATE_EVENT_FROM_MASTER);
962 ret = ERROR;
963 done = true;
964 break;
965 }
966
1/2
✓ Branch 0 taken 47 times.
✗ Branch 1 not taken.
47 delete ev;
967 }
968
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 if (relaylog_file_reader.has_fatal_error()) {
969 LogErr(ERROR_LEVEL, ER_RPL_RECOVERY_ERROR_READ_RELAY_LOG, -1);
970 return ERROR;
971 }
972 17 return ret;
973 17 }
974
975 /**
976 Reads relay logs one by one starting from the first relay log. Looks for
977 the first rotate event from the master. If rotate is not found in the relay
978 log search continues to next relay log. If rotate event from master is
979 found then the extracted master_log_file and master_log_pos are used to set
980 rli->group_master_log_name and rli->group_master_log_pos. If an error has
981 occurred the error code is returned back.
982
983 @param rli
984 Relay_log_info object to read relay log files and to set
985 group_master_log_name and group_master_log_pos.
986
987 @retval 0 Success - Rotate event was found
988 @retval 1 Failure - Found some events replicated but no rotate event was
989 found
990 @retval 2 When no rotate event from master was found. This can happen when
991 slave server was restarted immediately after executing CHANGE
992 MASTER
993 */
994 8 static int find_first_relay_log_with_rotate_from_master(Relay_log_info *rli) {
995
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 DBUG_TRACE;
996 8 int error = 0;
997 8 LOG_INFO linfo;
998 8 bool got_rotate_from_master = false;
999 int pos;
1000 char master_log_file[FN_REFLEN];
1001 8 my_off_t master_log_pos = 0;
1002
1003
2/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
8 if (channel_map.is_group_replication_channel_name(rli->get_channel())) {
1004 LogErr(INFORMATION_LEVEL,
1005 ER_RPL_RECOVERY_SKIPPED_GROUP_REPLICATION_CHANNEL);
1006 goto err;
1007 }
1008 #ifdef WITH_WSREP
1009 // Similar to GR, do not allow operations on the wsrep channel
1010
2/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
8 else if (wsrep_is_wsrep_channel_name(rli->get_channel())) {
1011 my_error(ER_SLAVE_CHANNEL_OPERATION_NOT_ALLOWED, MYF(0),
1012 "Relay log recovery skipped for '%s' channel", rli->get_channel());
1013 goto err;
1014 }
1015 #endif
1016
1017
3/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✓ Branch 3 taken 4 times.
21 for (pos = rli->relay_log.find_log_pos(&linfo, nullptr, true); !pos;
1018
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 pos = rli->relay_log.find_next_log(&linfo, true)) {
1019
3/6
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 13 times.
✗ Branch 5 not taken.
17 switch (read_rotate_from_relay_log(linfo.log_file_name, master_log_file,
1020 &master_log_pos)) {
1021 case ERROR:
1022 error = 1;
1023 break;
1024 4 case FOUND_ROTATE:
1025 4 got_rotate_from_master = true;
1026 4 break;
1027 13 case NOT_FOUND_ROTATE:
1028 13 break;
1029 }
1030
3/4
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 4 times.
17 if (error || got_rotate_from_master) break;
1031 }
1032
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (pos == LOG_INFO_IO) {
1033 error = 1;
1034 LogErr(ERROR_LEVEL, ER_RPL_RECOVERY_IO_ERROR_READING_RELAY_LOG_INDEX);
1035 goto err;
1036 }
1037
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
8 if (pos == LOG_INFO_EOF) {
1038 4 error = 2;
1039
8/16
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 4 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 4 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 4 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 4 times.
✗ Branch 15 not taken.
4 LogErr(WARNING_LEVEL, ER_RPL_RECOVERY_NO_ROTATE_EVENT_FROM_MASTER);
1040
8/16
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 4 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 4 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 4 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 4 times.
✗ Branch 15 not taken.
4 LogErr(WARNING_LEVEL, ER_WARN_RPL_RECOVERY_NO_ROTATE_EVENT_FROM_MASTER_EOF,
1041 rli->mi->get_channel());
1042 4 goto err;
1043 }
1044
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
4 if (!error && got_rotate_from_master) {
1045
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 rli->set_group_master_log_name(master_log_file);
1046 4 rli->set_group_master_log_pos(master_log_pos);
1047 }
1048 err:
1049 8 return error;
1050 8 }
1051
1052 /*
1053 Updates the master info based on the information stored in the
1054 relay info and ignores relay logs previously retrieved by the IO
1055 thread, which thus starts fetching again based on to the
1056 master_log_pos and master_log_name. Eventually, the old
1057 relay logs will be purged by the normal purge mechanism.
1058
1059 When GTID's are enabled the "Retrieved GTID" set should be cleared
1060 so that partial read events are discarded and they are
1061 fetched once again
1062
1063 @param mi pointer to Master_info instance
1064 */
1065 227 static void recover_relay_log(Master_info *mi) {
1066 227 Relay_log_info *rli = mi->rli;
1067
1068 // If GTID ONLY is enable the receiver doesn't care about these positions
1069
2/2
✓ Branch 0 taken 222 times.
✓ Branch 1 taken 5 times.
227 if (!mi->is_gtid_only_mode()) {
1070 // Set Receiver Thread's positions as per the recovered Applier Thread.
1071 222 mi->set_master_log_pos(std::max<ulonglong>(
1072 222 BIN_LOG_HEADER_SIZE, rli->get_group_master_log_pos()));
1073 222 mi->set_master_log_name(rli->get_group_master_log_name());
1074
1075
8/16
✓ Branch 0 taken 222 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 222 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 222 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 222 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 222 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 222 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 222 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 222 times.
✗ Branch 15 not taken.
222 LogErr(WARNING_LEVEL, ER_RPL_RECOVERY_FILE_MASTER_POS_INFO,
1076 (ulong)mi->get_master_log_pos(), mi->get_master_log_name(),
1077 mi->get_for_channel_str(), rli->get_group_relay_log_pos(),
1078 rli->get_group_relay_log_name());
1079 } else {
1080
7/14
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 5 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 5 times.
✗ Branch 13 not taken.
5 LogErr(WARNING_LEVEL, ER_RPL_RELAY_LOG_RECOVERY_GTID_ONLY);
1081 }
1082
1083 // Start with a fresh relay log.
1084 227 rli->set_group_relay_log_name(rli->relay_log.get_log_fname());
1085 227 rli->set_group_relay_log_pos(BIN_LOG_HEADER_SIZE);
1086 /*
1087 Clear the retrieved GTID set so that events that are written partially
1088 will be fetched again.
1089 */
1090
4/4
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 171 times.
✓ Branch 2 taken 54 times.
✓ Branch 3 taken 173 times.
283 if (global_gtid_mode.get() == Gtid_mode::ON &&
1091
2/2
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 2 times.
56 !channel_map.is_group_replication_channel_name(rli->get_channel())) {
1092 54 rli->get_sid_lock()->wrlock();
1093 54 (const_cast<Gtid_set *>(rli->get_gtid_set()))->clear_set_and_sid_map();
1094 54 rli->get_sid_lock()->unlock();
1095 }
1096 227 }
1097
1098 /*
1099 Updates the master info based on the information stored in the
1100 relay info and ignores relay logs previously retrieved by the IO
1101 thread, which thus starts fetching again based on to the
1102 master_log_pos and master_log_name. Eventually, the old
1103 relay logs will be purged by the normal purge mechanism.
1104
1105 There can be a special case where rli->group_master_log_name and
1106 rli->group_master_log_pos are not initialized, as the sql thread was never
1107 started at all. In those cases all the existing relay logs are parsed
1108 starting from the first one and the initial rotate event that was received
1109 from the master is identified. From the rotate event master_log_name and
1110 master_log_pos are extracted and they are set to rli->group_master_log_name
1111 and rli->group_master_log_pos.
1112
1113 In the feature, we should improve this routine in order to avoid throwing
1114 away logs that are safely stored in the disk. Note also that this recovery
1115 routine relies on the correctness of the relay-log.info and only tolerates
1116 coordinate problems in master.info.
1117
1118 In this function, there is no need for a mutex as the caller
1119 (i.e. init_replica) already has one acquired.
1120
1121 Specifically, the following structures are updated:
1122
1123 1 - mi->master_log_pos <-- rli->group_master_log_pos
1124 2 - mi->master_log_name <-- rli->group_master_log_name
1125 3 - It moves the relay log to the new relay log file, by
1126 rli->group_relay_log_pos <-- BIN_LOG_HEADER_SIZE;
1127 rli->event_relay_log_pos <-- BIN_LOG_HEADER_SIZE;
1128 rli->group_relay_log_name <-- rli->relay_log.get_log_fname();
1129 rli->event_relay_log_name <-- rli->relay_log.get_log_fname();
1130
1131 If there is an error, it returns (1), otherwise returns (0).
1132 */
1133 235 int init_recovery(Master_info *mi) {
1134
1/2
✓ Branch 0 taken 235 times.
✗ Branch 1 not taken.
235 DBUG_TRACE;
1135
1136 235 int error = 0;
1137 235 Relay_log_info *rli = mi->rli;
1138 235 char *group_master_log_name = nullptr;
1139
1140 /*
1141 This is not idempotent and a crash after this function and before
1142 the recovery is actually done may lead the system to an inconsistent
1143 state.
1144
1145 This may happen because the gap is not persitent stored anywhere
1146 and eventually old relay log files will be removed and further
1147 calculations on the gaps will be impossible.
1148
1149 We need to improve this. /Alfranio.
1150 */
1151
1/2
✓ Branch 0 taken 235 times.
✗ Branch 1 not taken.
235 error = mts_recovery_groups(rli);
1152
2/2
✓ Branch 0 taken 71 times.
✓ Branch 1 taken 164 times.
235 if (rli->mts_recovery_group_cnt) return error;
1153
1154 164 group_master_log_name = const_cast<char *>(rli->get_group_master_log_name());
1155
1/2
✓ Branch 0 taken 164 times.
✗ Branch 1 not taken.
164 if (!error) {
1156 164 bool run_relay_log_recovery = true;
1157
7/8
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 148 times.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11 times.
✓ Branch 5 taken 5 times.
✓ Branch 6 taken 11 times.
✓ Branch 7 taken 153 times.
164 if (!group_master_log_name[0] && !rli->mi->is_gtid_only_mode()) {
1158
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 8 times.
11 if (rli->replicate_same_server_id) {
1159 3 error = 1;
1160
8/16
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 3 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 3 times.
✗ Branch 15 not taken.
3 LogErr(ERROR_LEVEL,
1161 ER_RPL_RECOVERY_REPLICATE_SAME_SERVER_ID_REQUIRES_POSITION);
1162 3 return error;
1163 }
1164
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 error = find_first_relay_log_with_rotate_from_master(rli);
1165
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
8 if (error == 2) {
1166 // No events from the master on relay log - skip relay log recovery
1167 4 run_relay_log_recovery = false;
1168 4 error = 0;
1169
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 } else if (error)
1170 return error;
1171 }
1172
3/4
✓ Branch 0 taken 157 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 157 times.
✗ Branch 3 not taken.
161 if (run_relay_log_recovery) recover_relay_log(mi);
1173 }
1174 161 return error;
1175 235 }
1176
1177 /*
1178 Relay log recovery in the case of MTS, is handled by the following function.
1179 Gaps in MTS execution are filled using implicit execution of
1180 START SLAVE UNTIL SQL_AFTER_MTS_GAPS call. Once slave reaches a consistent
1181 gapless state receiver thread's positions are initialized to applier thread's
1182 positions and the old relay logs are discarded. This completes the recovery
1183 process.
1184
1185 @param mi pointer to Master_info instance.
1186
1187 @retval 0 success
1188 @retval 1 error
1189 */
1190 71 static inline int fill_mts_gaps_and_recover(Master_info *mi) {
1191
1/2
✓ Branch 0 taken 71 times.
✗ Branch 1 not taken.
71 DBUG_TRACE;
1192 71 Relay_log_info *rli = mi->rli;
1193 71 int recovery_error = 0;
1194 71 rli->is_relay_log_recovery = false;
1195
1/2
✓ Branch 0 taken 71 times.
✗ Branch 1 not taken.
71 Until_mts_gap *until_mg = new Until_mts_gap(rli);
1196
1/2
✓ Branch 0 taken 71 times.
✗ Branch 1 not taken.
71 rli->set_until_option(until_mg);
1197 71 rli->until_condition = Relay_log_info::UNTIL_SQL_AFTER_MTS_GAPS;
1198
1/2
✓ Branch 0 taken 71 times.
✗ Branch 1 not taken.
71 until_mg->init();
1199 71 rli->channel_mts_submode = (mts_parallel_option == MTS_PARALLEL_TYPE_DB_NAME)
1200 71 ? MTS_PARALLEL_TYPE_DB_NAME
1201 : MTS_PARALLEL_TYPE_LOGICAL_CLOCK;
1202
8/16
✓ Branch 0 taken 71 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 71 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 71 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 71 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 71 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 71 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 71 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 71 times.
✗ Branch 15 not taken.
71 LogErr(INFORMATION_LEVEL, ER_RPL_MTS_RECOVERY_STARTING_COORDINATOR);
1203
1/2
✓ Branch 0 taken 71 times.
✗ Branch 1 not taken.
71 recovery_error = start_slave_thread(
1204 key_thread_replica_sql, handle_slave_sql, &rli->run_lock, &rli->run_lock,
1205 &rli->start_cond, &rli->slave_running, &rli->slave_run_id, mi);
1206
1207
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 71 times.
71 if (recovery_error) {
1208 LogErr(WARNING_LEVEL, ER_RPL_MTS_RECOVERY_FAILED_TO_START_COORDINATOR);
1209 goto err;
1210 }
1211
1/2
✓ Branch 0 taken 71 times.
✗ Branch 1 not taken.
71 mysql_mutex_lock(&rli->run_lock);
1212
1/2
✓ Branch 0 taken 71 times.
✗ Branch 1 not taken.
71 mysql_cond_wait(&rli->stop_cond, &rli->run_lock);
1213
1/2
✓ Branch 0 taken 71 times.
✗ Branch 1 not taken.
71 mysql_mutex_unlock(&rli->run_lock);
1214
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 70 times.
71 if (rli->until_condition != Relay_log_info::UNTIL_DONE) {
1215
8/16
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
1 LogErr(WARNING_LEVEL, ER_RPL_MTS_AUTOMATIC_RECOVERY_FAILED);
1216 1 goto err;
1217 }
1218
1/2
✓ Branch 0 taken 70 times.
✗ Branch 1 not taken.
70 rli->clear_until_option();
1219 /*
1220 We need a mutex while we are changing master info parameters to
1221 keep other threads from reading bogus info
1222 */
1223
1/2
✓ Branch 0 taken 70 times.
✗ Branch 1 not taken.
70 mysql_mutex_lock(&mi->data_lock);
1224
1/2
✓ Branch 0 taken 70 times.
✗ Branch 1 not taken.
70 mysql_mutex_lock(&rli->data_lock);
1225
1/2
✓ Branch 0 taken 70 times.
✗ Branch 1 not taken.
70 recover_relay_log(mi);
1226
1227
3/6
✓ Branch 0 taken 70 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 70 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 70 times.
140 if (mi->flush_info(true) ||
1228
2/4
✓ Branch 0 taken 70 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 70 times.
70 rli->flush_info(Relay_log_info::RLI_FLUSH_IGNORE_SYNC_OPT)) {
1229 recovery_error = 1;
1230 mysql_mutex_unlock(&mi->data_lock);
1231 mysql_mutex_unlock(&rli->data_lock);
1232 goto err;
1233 }
1234 70 rli->inited = true;
1235 70 rli->error_on_rli_init_info = false;
1236
1/2
✓ Branch 0 taken 70 times.
✗ Branch 1 not taken.
70 mysql_mutex_unlock(&mi->data_lock);
1237
1/2
✓ Branch 0 taken 70 times.
✗ Branch 1 not taken.
70 mysql_mutex_unlock(&rli->data_lock);
1238
8/16
✓ Branch 0 taken 70 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 70 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 70 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 70 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 70 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 70 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 70 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 70 times.
✗ Branch 15 not taken.
70 LogErr(INFORMATION_LEVEL, ER_RPL_MTS_RECOVERY_SUCCESSFUL);
1239 70 return recovery_error;
1240 1 err:
1241 /*
1242 If recovery failed means we failed to initialize rli object in the case
1243 of MTS. We should not allow the START SLAVE command to work as we do in
1244 the case of STS. i.e if init_recovery call fails then we set inited=0.
1245 */
1246
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 rli->end_info();
1247 1 rli->inited = false;
1248 1 rli->error_on_rli_init_info = true;
1249
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 rli->clear_until_option();
1250 1 return recovery_error;
1251 71 }
1252
1253 24693 int load_mi_and_rli_from_repositories(Master_info *mi, bool ignore_if_no_info,
1254 int thread_mask,
1255 bool skip_received_gtid_set_recovery,
1256 bool force_load) {
1257
1/2
✓ Branch 0 taken 24693 times.
✗ Branch 1 not taken.
24693 DBUG_TRACE;
1258
2/4
✓ Branch 0 taken 24693 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24693 times.
✗ Branch 3 not taken.
24693 assert(mi != nullptr && mi->rli != nullptr);
1259 24693 int init_error = 0;
1260 24693 enum_return_check check_return = ERROR_CHECKING_REPOSITORY;
1261
1/2
✓ Branch 0 taken 24693 times.
✗ Branch 1 not taken.
24693 THD *thd = current_thd;
1262
1263 /*
1264 We need a mutex while we are changing master info parameters to
1265 keep other threads from reading bogus info
1266 */
1267
1/2
✓ Branch 0 taken 24693 times.
✗ Branch 1 not taken.
24693 mysql_mutex_lock(&mi->data_lock);
1268
1/2
✓ Branch 0 taken 24693 times.
✗ Branch 1 not taken.
24693 mysql_mutex_lock(&mi->rli->data_lock);
1269
1270 /*
1271 When info tables are used and autocommit= 0 we force a new
1272 transaction start to avoid table access deadlocks when START SLAVE
1273 is executed after RESET SLAVE.
1274 */
1275
3/4
✓ Branch 0 taken 24693 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 24688 times.
24693 if (is_autocommit_off_and_infotables(thd)) {
1276
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 if (trans_begin(thd)) {
1277 init_error = 1;
1278 goto end;
1279 }
1280 }
1281
1282 /*
1283 This takes care of the startup dependency between the master_info
1284 and relay_info. It initializes the master info if the SLAVE_IO
1285 thread is being started and the relay log info if either the
1286 SLAVE_SQL thread is being started or was not initialized as it is
1287 required by the SLAVE_IO thread.
1288 */
1289
1/2
✓ Branch 0 taken 24687 times.
✗ Branch 1 not taken.
24693 check_return = mi->check_info();
1290
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 24685 times.
24687 if (check_return == ERROR_CHECKING_REPOSITORY) {
1291 2 init_error = 1;
1292 2 goto end;
1293 }
1294
1295
3/4
✓ Branch 0 taken 675 times.
✓ Branch 1 taken 24010 times.
✓ Branch 2 taken 675 times.
✗ Branch 3 not taken.
24685 if (!ignore_if_no_info || check_return != REPOSITORY_DOES_NOT_EXIST) {
1296
2/2
✓ Branch 0 taken 20942 times.
✓ Branch 1 taken 3743 times.
24685 if ((thread_mask & SLAVE_IO) != 0) {
1297
3/4
✓ Branch 0 taken 9120 times.
✓ Branch 1 taken 11822 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 9120 times.
20942 if (!mi->inited || force_load) {
1298
3/4
✓ Branch 0 taken 11822 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 11818 times.
11822 if (mi->mi_init_info()) {
1299 4 init_error = 1;
1300 }
1301 }
1302 }
1303 }
1304
1305
1/2
✓ Branch 0 taken 24685 times.
✗ Branch 1 not taken.
24685 check_return = mi->rli->check_info();
1306
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24685 times.
24685 if (check_return == ERROR_CHECKING_REPOSITORY) {
1307 init_error = 1;
1308 goto end;
1309 }
1310
4/4
✓ Branch 0 taken 675 times.
✓ Branch 1 taken 24010 times.
✓ Branch 2 taken 672 times.
✓ Branch 3 taken 3 times.
24685 if (!ignore_if_no_info || check_return != REPOSITORY_DOES_NOT_EXIST) {
1311
4/4
✓ Branch 0 taken 749 times.
✓ Branch 1 taken 23933 times.
✓ Branch 2 taken 26 times.
✓ Branch 3 taken 723 times.
24682 if ((thread_mask & SLAVE_SQL) != 0 || !(mi->rli->inited)) {
1312
4/4
✓ Branch 0 taken 12132 times.
✓ Branch 1 taken 11827 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 12114 times.
23959 if (!mi->rli->inited || force_load) {
1313
3/4
✓ Branch 0 taken 11845 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 11836 times.
11845 if (mi->rli->rli_init_info(skip_received_gtid_set_recovery)) {
1314 9 init_error = 1;
1315 } else {
1316 /*
1317 During rli_init_info() above, the relay log is opened (if rli was
1318 not initialized yet). The function below expects the relay log to be
1319 opened to get its coordinates and store as the last flushed relay
1320 log coordinates from I/O thread point of view.
1321 */
1322
1/2
✓ Branch 0 taken 11836 times.
✗ Branch 1 not taken.
11836 mi->update_flushed_relay_log_info();
1323 }
1324 } else {
1325 // Even if we skip rli_init_info we must check if gaps exist to maintain
1326 // the server behavior in commands like CHANGE REPLICATION SOURCE
1327
5/6
✓ Branch 0 taken 4012 times.
✓ Branch 1 taken 8102 times.
✓ Branch 2 taken 4012 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 12113 times.
12114 if (mi->rli->recovery_parallel_workers ? mts_recovery_groups(mi->rli)
1328 : 0)
1329 1 init_error = 1;
1330 }
1331 }
1332 }
1333
1334
2/6
✓ Branch 0 taken 24685 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24685 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
24685 DBUG_EXECUTE_IF("enable_mta_worker_failure_init",
1335 { DBUG_SET("+d,mta_worker_thread_init_fails"); });
1336 24685 end:
1337 /*
1338 When info tables are used and autocommit= 0 we force transaction
1339 commit to avoid table access deadlocks when START SLAVE is executed
1340 after RESET SLAVE.
1341 */
1342
3/4
✓ Branch 0 taken 24687 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 24682 times.
24687 if (is_autocommit_off_and_infotables(thd))
1343
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 if (trans_commit(thd)) init_error = 1;
1344
1345
1/2
✓ Branch 0 taken 24687 times.
✗ Branch 1 not taken.
24687 mysql_mutex_unlock(&mi->rli->data_lock);
1346
1/2
✓ Branch 0 taken 24687 times.
✗ Branch 1 not taken.
24687 mysql_mutex_unlock(&mi->data_lock);
1347
1348 /*
1349 Handling MTS Relay-log recovery after successful initialization of mi and
1350 rli objects.
1351
1352 MTS Relay-log recovery is handled by SSUG command. In order to start the
1353 slave applier thread rli needs to be inited and mi->rli->data_lock should
1354 be in released state. Hence we do the MTS recovery at this point of time
1355 where both conditions are satisfied.
1356 */
1357
4/4
✓ Branch 0 taken 24671 times.
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 71 times.
✓ Branch 3 taken 24600 times.
24687 if (!init_error && mi->rli->is_relay_log_recovery &&
1358
1/2
✓ Branch 0 taken 71 times.
✗ Branch 1 not taken.
71 mi->rli->mts_recovery_group_cnt)
1359
1/2
✓ Branch 0 taken 71 times.
✗ Branch 1 not taken.
71 init_error = fill_mts_gaps_and_recover(mi);
1360 24687 return init_error;
1361 24687 }
1362
1363 22006 void end_info(Master_info *mi) {
1364
1/2
✓ Branch 0 taken 22006 times.
✗ Branch 1 not taken.
22006 DBUG_TRACE;
1365
2/4
✓ Branch 0 taken 22006 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 22006 times.
✗ Branch 3 not taken.
22006 assert(mi != nullptr && mi->rli != nullptr);
1366
1367 /*
1368 The previous implementation was not acquiring locks. We do the same here.
1369 However, this is quite strange.
1370 */
1371
1/2
✓ Branch 0 taken 22006 times.
✗ Branch 1 not taken.
22006 mi->end_info();
1372
1/2
✓ Branch 0 taken 22006 times.
✗ Branch 1 not taken.
22006 mi->rli->end_info();
1373 22006 }
1374
1375 12597 void clear_info(Master_info *mi) {
1376
1/2
✓ Branch 0 taken 12597 times.
✗ Branch 1 not taken.
12597 DBUG_TRACE;
1377
2/4
✓ Branch 0 taken 12597 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12597 times.
✗ Branch 3 not taken.
12597 assert(mi != nullptr && mi->rli != nullptr);
1378
1379 /*
1380 Reset errors (the idea is that we forget about the
1381 old master).
1382 */
1383
1/2
✓ Branch 0 taken 12597 times.
✗ Branch 1 not taken.
12597 mi->clear_error();
1384
1/2
✓ Branch 0 taken 12597 times.
✗ Branch 1 not taken.
12597 mi->rli->clear_error();
1385
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12597 times.
12597 if (mi->rli->workers_array_initialized) {
1386 for (size_t i = 0; i < mi->rli->get_worker_count(); i++) {
1387 mi->rli->get_worker(i)->clear_error();
1388 }
1389 }
1390 12597 mi->rli->clear_sql_delay();
1391
1392
1/2
✓ Branch 0 taken 12597 times.
✗ Branch 1 not taken.
12597 end_info(mi);
1393 12597 }
1394
1395 8923 int remove_info(Master_info *mi) {
1396 8923 int error = 1;
1397
1/2
✓ Branch 0 taken 8923 times.
✗ Branch 1 not taken.
8923 DBUG_TRACE;
1398
2/4
✓ Branch 0 taken 8923 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8923 times.
✗ Branch 3 not taken.
8923 assert(mi != nullptr && mi->rli != nullptr);
1399
1400 /*
1401 The previous implementation was not acquiring locks.
1402 We do the same here. However, this is quite strange.
1403 */
1404
1/2
✓ Branch 0 taken 8923 times.
✗ Branch 1 not taken.
8923 clear_info(mi);
1405
1406
7/10
✓ Branch 0 taken 8923 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8923 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8923 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 8922 times.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 8922 times.
17845 if (mi->remove_info() || Rpl_info_factory::reset_workers(mi->rli) ||
1407
2/4
✓ Branch 0 taken 8922 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 8922 times.
8922 mi->rli->remove_info())
1408 1 goto err;
1409
1410 8922 error = 0;
1411
1412 8923 err:
1413 8923 return error;
1414 8923 }
1415
1416 3674 bool reset_info(Master_info *mi) {
1417
1/2
✓ Branch 0 taken 3674 times.
✗ Branch 1 not taken.
3674 DBUG_TRACE;
1418
2/4
✓ Branch 0 taken 3674 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3674 times.
✗ Branch 3 not taken.
3674 assert(mi != nullptr && mi->rli != nullptr);
1419
1420
1/2
✓ Branch 0 taken 3674 times.
✗ Branch 1 not taken.
3674 clear_info(mi);
1421
1422
5/10
✓ Branch 0 taken 3674 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3674 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3674 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 3674 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 3674 times.
3674 if (mi->remove_info() || Rpl_info_factory::reset_workers(mi->rli))
1423 return true;
1424
1425 3674 MUTEX_LOCK(mi_lock, &mi->data_lock);
1426 3674 MUTEX_LOCK(rli_lock, &mi->rli->data_lock);
1427
1428
1/2
✓ Branch 0 taken 3674 times.
✗ Branch 1 not taken.
3674 mi->init_master_log_pos();
1429 3674 mi->master_uuid[0] = 0;
1430
1431
2/2
✓ Branch 0 taken 3636 times.
✓ Branch 1 taken 14 times.
3650 if (mi->reset && opt_mi_repository_id == INFO_REPOSITORY_TABLE &&
1432
7/10
✓ Branch 0 taken 3650 times.
✓ Branch 1 taken 24 times.
✓ Branch 2 taken 3633 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 3633 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 3633 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 3674 times.
7324 opt_rli_repository_id == INFO_REPOSITORY_TABLE && mi->flush_info(true)) {
1433 my_error(ER_MASTER_INFO, MYF(0));
1434 return true;
1435 }
1436
1437 bool have_relay_log_data_to_persist = // Only want to keep
1438
1/2
✓ Branch 0 taken 3674 times.
✗ Branch 1 not taken.
3674 (!mi->rli->is_privilege_checks_user_null() || // if PCU is not null
1439
3/4
✓ Branch 0 taken 3658 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 990 times.
✓ Branch 3 taken 2668 times.
3658 mi->rli->is_row_format_required() || // or RRF is 1
1440 Relay_log_info::PK_CHECK_STREAM != // or RTPKC != STREAM
1441
2/4
✓ Branch 0 taken 990 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 990 times.
990 mi->rli->get_require_table_primary_key_check()) &&
1442
3/4
✓ Branch 0 taken 3658 times.
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 2684 times.
✗ Branch 3 not taken.
10016 opt_rli_repository_id == INFO_REPOSITORY_TABLE && // in TABLE repository.
1443
1/2
✓ Branch 0 taken 2684 times.
✗ Branch 1 not taken.
2684 opt_mi_repository_id == INFO_REPOSITORY_TABLE;
1444
1445
5/8
✓ Branch 0 taken 2684 times.
✓ Branch 1 taken 990 times.
✓ Branch 2 taken 2684 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2684 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 3674 times.
7348 if ((have_relay_log_data_to_persist && mi->rli->clear_info()) ||
1446
4/6
✓ Branch 0 taken 990 times.
✓ Branch 1 taken 2684 times.
✓ Branch 2 taken 990 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 990 times.
3674 (!have_relay_log_data_to_persist && mi->rli->remove_info())) {
1447 my_error(ER_MASTER_INFO, MYF(0));
1448 return true;
1449 }
1450
1451 3674 return false;
1452 3674 }
1453
1454 1354903 int flush_master_info(Master_info *mi, bool force, bool need_lock,
1455 bool do_flush_relay_log, bool skip_repo_persistence) {
1456
1/2
✓ Branch 0 taken 1354903 times.
✗ Branch 1 not taken.
1354903 DBUG_TRACE;
1457
2/4
✓ Branch 0 taken 1354903 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1354903 times.
✗ Branch 3 not taken.
1354903 assert(mi != nullptr && mi->rli != nullptr);
1458
3/4
✓ Branch 0 taken 1354903 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1354902 times.
1354903 DBUG_EXECUTE_IF("fail_to_flush_source_info", { return 1; });
1459
1460
3/4
✓ Branch 0 taken 61383 times.
✓ Branch 1 taken 1293519 times.
✓ Branch 2 taken 61383 times.
✗ Branch 3 not taken.
1354902 if (skip_repo_persistence && !do_flush_relay_log) {
1461 61383 return 0;
1462 }
1463
1464 /*
1465 With the appropriate recovery process, we will not need to flush
1466 the content of the current log.
1467
1468 For now, we flush the relay log BEFORE the master.info file, because
1469 if we crash, we will get a duplicate event in the relay log at restart.
1470 If we change the order, there might be missing events.
1471
1472 If we don't do this and the slave server dies when the relay log has
1473 some parts (its last kilobytes) in memory only, with, say, from master's
1474 position 100 to 150 in memory only (not on disk), and with position 150
1475 in master.info, there will be missing information. When the slave restarts,
1476 the I/O thread will fetch binlogs from 150, so in the relay log we will
1477 have "[0, 100] U [150, infinity[" and nobody will notice it, so the SQL
1478 thread will jump from 100 to 150, and replication will silently break.
1479 */
1480 1293519 mysql_mutex_t *log_lock = mi->rli->relay_log.get_log_lock();
1481 1293519 mysql_mutex_t *data_lock = &mi->data_lock;
1482
1483
2/2
✓ Branch 0 taken 12507 times.
✓ Branch 1 taken 1281012 times.
1293519 if (need_lock) {
1484
1/2
✓ Branch 0 taken 12507 times.
✗ Branch 1 not taken.
12507 mysql_mutex_lock(log_lock);
1485
1/2
✓ Branch 0 taken 12507 times.
✗ Branch 1 not taken.
12507 mysql_mutex_lock(data_lock);
1486 } else {
1487 mysql_mutex_assert_owner(log_lock);
1488 mysql_mutex_assert_owner(&mi->data_lock);
1489 }
1490
1491 1293519 int err = 0;
1492 /*
1493 We can skip flushing the relay log when this function is called from
1494 queue_event(), as after_write_to_relay_log() will already flush it.
1495 */
1496
3/4
✓ Branch 0 taken 12477 times.
✓ Branch 1 taken 1281042 times.
✓ Branch 2 taken 12477 times.
✗ Branch 3 not taken.
1293519 if (do_flush_relay_log) err |= mi->rli->flush_current_log();
1497
1498
2/4
✓ Branch 0 taken 1293519 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1293519 times.
✗ Branch 3 not taken.
1293519 if (!skip_repo_persistence) err |= mi->flush_info(force);
1499
1500
2/2
✓ Branch 0 taken 12507 times.
✓ Branch 1 taken 1281012 times.
1293519 if (need_lock) {
1501
1/2
✓ Branch 0 taken 12507 times.
✗ Branch 1 not taken.
12507 mysql_mutex_unlock(data_lock);
1502
1/2
✓ Branch 0 taken 12507 times.
✗ Branch 1 not taken.
12507 mysql_mutex_unlock(log_lock);
1503 }
1504
1505 1293519 return err;
1506 1354903 }
1507
1508 /**
1509 Convert slave skip errors bitmap into a printable string.
1510 */
1511
1512 9181 static void print_replica_skip_errors(void) {
1513 /*
1514 To be safe, we want 10 characters of room in the buffer for a number
1515 plus terminators. Also, we need some space for constant strings.
1516 10 characters must be sufficient for a number plus {',' | '...'}
1517 plus a NUL terminator. That is a max 6 digit number.
1518 */
1519 9181 const size_t MIN_ROOM = 10;
1520
1/2
✓ Branch 0 taken 9181 times.
✗ Branch 1 not taken.
9181 DBUG_TRACE;
1521 assert(sizeof(slave_skip_error_names) > MIN_ROOM);
1522 assert(MAX_SLAVE_ERROR <= 999999); // 6 digits
1523
1524
7/8
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 9147 times.
✓ Branch 2 taken 34 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 33 times.
✓ Branch 6 taken 9148 times.
✓ Branch 7 taken 33 times.
9181 if (!use_slave_mask || bitmap_is_clear_all(&slave_error_mask)) {
1525 /* purecov: begin tested */
1526 9148 memcpy(slave_skip_error_names, STRING_WITH_LEN("OFF"));
1527 /* purecov: end */
1528
3/4
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 31 times.
33 } else if (bitmap_is_set_all(&slave_error_mask)) {
1529 /* purecov: begin tested */
1530 2 memcpy(slave_skip_error_names, STRING_WITH_LEN("ALL"));
1531 /* purecov: end */
1532 } else {
1533 31 char *buff = slave_skip_error_names;
1534 31 char *bend = buff + sizeof(slave_skip_error_names);
1535 int errnum;
1536
1537
2/2
✓ Branch 0 taken 434000 times.
✓ Branch 1 taken 31 times.
434031 for (errnum = 0; errnum < MAX_SLAVE_ERROR; errnum++) {
1538
2/2
✓ Branch 0 taken 74 times.
✓ Branch 1 taken 433926 times.
434000 if (bitmap_is_set(&slave_error_mask, errnum)) {
1539
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 74 times.
74 if (buff + MIN_ROOM >= bend) break; /* purecov: tested */
1540
1/2
✓ Branch 0 taken 74 times.
✗ Branch 1 not taken.
74 buff = longlong10_to_str(errnum, buff, -10);
1541 74 *buff++ = ',';
1542 }
1543 }
1544
1/2
✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
31 if (buff != slave_skip_error_names) buff--; // Remove last ','
1545 /*
1546 The range for client side error is [2000-2999]
1547 so if the errnum doesn't lie in that and if less
1548 than MAX_SLAVE_ERROR[10000] we enter the if loop.
1549 */
1550
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
31 if (errnum < MAX_SLAVE_ERROR &&
1551 (errnum < CR_MIN_ERROR || errnum > CR_MAX_ERROR)) {
1552 /* Couldn't show all errors */
1553 buff = my_stpcpy(buff, "..."); /* purecov: tested */
1554 }
1555 31 *buff = 0;
1556 }
1557
3/8
✓ Branch 0 taken 9181 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9181 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 9181 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
9181 DBUG_PRINT("init", ("error_names: '%s'", slave_skip_error_names));
1558 9181 }
1559
1560 /**
1561 Change arg to the string with the nice, human-readable skip error values.
1562 @param replica_skip_errors_ptr
1563 The pointer to be changed
1564 */
1565 9181 void set_replica_skip_errors(char **replica_skip_errors_ptr) {
1566
1/2
✓ Branch 0 taken 9181 times.
✗ Branch 1 not taken.
9181 DBUG_TRACE;
1567
1/2
✓ Branch 0 taken 9181 times.
✗ Branch 1 not taken.
9181 print_replica_skip_errors();
1568 9181 *replica_skip_errors_ptr = slave_skip_error_names;
1569 9181 }
1570
1571 /**
1572 Init function to set up array for errors that should be skipped for slave
1573 */
1574 34 static void init_replica_skip_errors() {
1575
1/2
✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
34 DBUG_TRACE;
1576
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
34 assert(!use_slave_mask); // not already initialized
1577
1578
2/4
✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 34 times.
34 if (bitmap_init(&slave_error_mask, nullptr, MAX_SLAVE_ERROR)) {
1579 fprintf(stderr, "Badly out of memory, please check your system status\n");
1580 exit(MYSQLD_ABORT_EXIT);
1581 }
1582 34 use_slave_mask = true;
1583 34 }
1584
1585 1 static void add_replica_skip_errors(const uint *errors, uint n_errors) {
1586
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 DBUG_TRACE;
1587
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 assert(errors);
1588
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 assert(use_slave_mask);
1589
1590
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 1 times.
11 for (uint i = 0; i < n_errors; i++) {
1591 10 const uint err_code = errors[i];
1592 /*
1593 The range for client side error is [2000-2999]
1594 so if the err_code doesn't lie in that and if less
1595 than MAX_SLAVE_ERROR[14000] we enter the if loop.
1596 */
1597
2/4
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
10 if (err_code < MAX_SLAVE_ERROR &&
1598 (err_code < CR_MIN_ERROR || err_code > CR_MAX_ERROR))
1599 10 bitmap_set_bit(&slave_error_mask, err_code);
1600 }
1601 1 }
1602
1603 /*
1604 Add errors that should be skipped for slave
1605
1606 SYNOPSIS
1607 add_replica_skip_errors()
1608 arg List of errors numbers to be added to skip, separated with ','
1609
1610 NOTES
1611 Called from get_options() in mysqld.cc on start-up
1612 */
1613
1614 34 void add_replica_skip_errors(const char *arg) {
1615 34 const char *p = nullptr;
1616 /*
1617 ALL is only valid when nothing else is provided.
1618 */
1619 34 const uchar SKIP_ALL[] = "all";
1620 34 size_t SIZE_SKIP_ALL = strlen((const char *)SKIP_ALL) + 1;
1621 /*
1622 IGNORE_DDL_ERRORS can be combined with other parameters
1623 but must be the first one provided.
1624 */
1625 34 const uchar SKIP_DDL_ERRORS[] = "ddl_exist_errors";
1626 34 size_t SIZE_SKIP_DDL_ERRORS = strlen((const char *)SKIP_DDL_ERRORS);
1627
1/2
✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
34 DBUG_TRACE;
1628
1629 // initialize mask if not done yet
1630
2/4
✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 34 times.
✗ Branch 3 not taken.
34 if (!use_slave_mask) init_replica_skip_errors();
1631
1632
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
34 for (; my_isspace(system_charset_info, *arg); ++arg) /* empty */
1633 ;
1634
3/4
✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 32 times.
34 if (!my_strnncoll(system_charset_info, pointer_cast<const uchar *>(arg),
1635 SIZE_SKIP_ALL, SKIP_ALL, SIZE_SKIP_ALL)) {
1636 2 bitmap_set_all(&slave_error_mask);
1637 2 return;
1638 }
1639
3/4
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 31 times.
32 if (!my_strnncoll(system_charset_info, pointer_cast<const uchar *>(arg),
1640 SIZE_SKIP_DDL_ERRORS, SKIP_DDL_ERRORS,
1641 SIZE_SKIP_DDL_ERRORS)) {
1642 // DDL errors to be skipped for relaxed 'exist' handling
1643 1 const uint ddl_errors[] = {
1644 // error codes with create/add <schema object>
1645 ER_DB_CREATE_EXISTS, ER_TABLE_EXISTS_ERROR, ER_DUP_KEYNAME,
1646 ER_MULTIPLE_PRI_KEY,
1647 // error codes with change/rename <schema object>
1648 ER_BAD_FIELD_ERROR, ER_NO_SUCH_TABLE, ER_DUP_FIELDNAME,
1649 // error codes with drop <schema object>
1650 ER_DB_DROP_EXISTS, ER_BAD_TABLE_ERROR, ER_CANT_DROP_FIELD_OR_KEY};
1651
1652
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 add_replica_skip_errors(ddl_errors,
1653 sizeof(ddl_errors) / sizeof(ddl_errors[0]));
1654 /*
1655 After processing the SKIP_DDL_ERRORS, the pointer is
1656 increased to the position after the comma.
1657 */
1658
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (strlen(arg) > SIZE_SKIP_DDL_ERRORS + 1) arg += SIZE_SKIP_DDL_ERRORS + 1;
1659 }
1660
2/2
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 31 times.
96 for (p = arg; *p;) {
1661 long err_code;
1662
3/4
✓ Branch 0 taken 65 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 64 times.
65 if (!(p = str2int(p, 10, 0, LONG_MAX, &err_code))) break;
1663
1/2
✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
64 if (err_code < MAX_SLAVE_ERROR)
1664 64 bitmap_set_bit(&slave_error_mask, (uint)err_code);
1665
4/4
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 33 times.
✓ Branch 2 taken 33 times.
✓ Branch 3 taken 31 times.
97 while (!my_isdigit(system_charset_info, *p) && *p) p++;
1666 }
1667
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 2 times.
34 }
1668
1669 19749 static void set_thd_in_use_temporary_tables(Relay_log_info *rli) {
1670 TABLE *table;
1671
1672
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 19749 times.
19782 for (table = rli->save_temporary_tables; table; table = table->next) {
1673 33 table->in_use = rli->info_thd;
1674
1/2
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
33 if (table->file != nullptr) {
1675 /*
1676 Since we are stealing opened temporary tables from one thread to
1677 another, we need to let the performance schema know that, for aggregates
1678 per thread to work properly.
1679 */
1680 33 table->file->unbind_psi();
1681 33 table->file->rebind_psi();
1682 }
1683 }
1684 19749 }
1685
1686 17149 int terminate_slave_threads(Master_info *mi, int thread_mask,
1687 ulong stop_wait_timeout, bool need_lock_term) {
1688
1/2
✓ Branch 0 taken 17149 times.
✗ Branch 1 not taken.
17149 DBUG_TRACE;
1689
1690
2/2
✓ Branch 0 taken 6116 times.
✓ Branch 1 taken 11033 times.
17149 if (!mi->inited) return 0; /* successfully do nothing */
1691 11033 int error, force_all = (thread_mask & SLAVE_FORCE_ALL);
1692 11033 mysql_mutex_t *sql_lock{&mi->rli->run_lock}, *io_lock{&mi->run_lock};
1693 11033 mysql_mutex_t *log_lock = mi->rli->relay_log.get_log_lock();
1694 /*
1695 Set it to a variable, so the value is shared by both stop methods.
1696 This guarantees that the user defined value for the timeout value is for
1697 the time the 2 threads take to shutdown, and not the time of each thread
1698 stop operation.
1699 */
1700 11033 ulong total_stop_wait_timeout = stop_wait_timeout;
1701
1702
2/2
✓ Branch 0 taken 10260 times.
✓ Branch 1 taken 773 times.
11033 if (thread_mask & (SLAVE_SQL | SLAVE_FORCE_ALL)) {
1703
3/8
✓ Branch 0 taken 10260 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10260 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 10260 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
10260 DBUG_PRINT("info", ("Terminating SQL thread"));
1704 10260 mi->rli->abort_slave = true;
1705 30780 if ((error = terminate_slave_thread(
1706 10260 mi->rli->info_thd, sql_lock, &mi->rli->stop_cond,
1707
1/2
✓ Branch 0 taken 10260 times.
✗ Branch 1 not taken.
10260 &mi->rli->slave_running, &total_stop_wait_timeout,
1708
5/6
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 10252 times.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✓ Branch 5 taken 10252 times.
10260 need_lock_term)) &&
1709 !force_all) {
1710
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (error == 1) {
1711 8 return ER_STOP_SLAVE_SQL_THREAD_TIMEOUT;
1712 }
1713 return error;
1714 }
1715
1716
3/8
✓ Branch 0 taken 10252 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10252 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 10252 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
10252 DBUG_PRINT("info", ("Flushing relay-log info file."));
1717
3/4
✓ Branch 0 taken 10252 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8471 times.
✓ Branch 3 taken 1781 times.
10252 if (current_thd)
1718
2/4
✓ Branch 0 taken 8471 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8471 times.
✗ Branch 3 not taken.
8471 THD_STAGE_INFO(current_thd, stage_flushing_relay_log_info_file);
1719
1720 /*
1721 Flushes the relay log info regardless of the sync_relay_log_info option.
1722 */
1723
2/4
✓ Branch 0 taken 10252 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10252 times.
10252 if (mi->rli->flush_info(Relay_log_info::RLI_FLUSH_IGNORE_SYNC_OPT)) {
1724 return ER_ERROR_DURING_FLUSH_LOGS;
1725 }
1726 }
1727
1728 /*
1729 Only stops the monitoring thread if this is the only failover channel
1730 running.
1731 */
1732
4/4
✓ Branch 0 taken 1850 times.
✓ Branch 1 taken 9175 times.
✓ Branch 2 taken 68 times.
✓ Branch 3 taken 10957 times.
12875 if ((thread_mask & (SLAVE_MONITOR | SLAVE_FORCE_ALL)) &&
1733
3/4
✓ Branch 0 taken 1850 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 68 times.
✓ Branch 3 taken 1782 times.
1850 channel_map.get_number_of_connection_auto_failover_channels_running() ==
1734 1) {
1735
3/8
✓ Branch 0 taken 68 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 68 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 68 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
68 DBUG_PRINT("info", ("Terminating Monitor IO thread"));
1736 68 if ((error = Source_IO_monitor::get_instance()
1737
4/10
✓ Branch 0 taken 68 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 68 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 68 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 68 times.
68 ->terminate_monitoring_process()) &&
1738 !force_all) {
1739 if (error == 1) {
1740 return ER_STOP_REPLICA_MONITOR_IO_THREAD_TIMEOUT;
1741 }
1742 return error;
1743 }
1744 }
1745
1746
2/2
✓ Branch 0 taken 8076 times.
✓ Branch 1 taken 2949 times.
11025 if (thread_mask & (SLAVE_IO | SLAVE_FORCE_ALL)) {
1747
3/8
✓ Branch 0 taken 8076 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8076 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 8076 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
8076 DBUG_PRINT("info", ("Terminating IO thread"));
1748 8076 mi->abort_slave = true;
1749
4/6
✓ Branch 0 taken 8076 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 8074 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
8076 DBUG_EXECUTE_IF("pause_after_queue_event",
1750 { rpl_replica_debug_point(DBUG_RPL_S_PAUSE_QUEUE_EV); });
1751 /*
1752 If the I/O thread is running and waiting for disk space,
1753 the signal above will not make it to stop.
1754 */
1755 bool io_waiting_disk_space =
1756
4/4
✓ Branch 0 taken 6473 times.
✓ Branch 1 taken 1603 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 6467 times.
8076 mi->slave_running && mi->info_thd->is_waiting_for_disk_space();
1757
1758 /*
1759 If we are shutting down the server and the I/O thread is waiting for
1760 disk space, tell the terminate_slave_thread to forcefully kill the I/O
1761 thread by sending a KILL_CONNECTION signal that will be listened by
1762 my_write function.
1763 */
1764 8076 bool force_io_stop =
1765
4/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 8070 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 3 times.
8076 io_waiting_disk_space && (thread_mask & SLAVE_FORCE_ALL);
1766
1767 // If not shutting down, let the user to decide to abort I/O thread or wait
1768
4/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 8070 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 3 times.
8076 if (io_waiting_disk_space && !force_io_stop) {
1769
8/16
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 3 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 3 times.
✗ Branch 15 not taken.
3 LogErr(WARNING_LEVEL, ER_STOP_SLAVE_IO_THREAD_DISK_SPACE,
1770 mi->get_channel());
1771
3/6
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
3 DBUG_EXECUTE_IF("simulate_io_thd_wait_for_disk_space", {
1772 rpl_replica_debug_point(DBUG_RPL_S_IO_WAIT_FOR_SPACE);
1773 });
1774 }
1775
1776
1/2
✓ Branch 0 taken 8076 times.
✗ Branch 1 not taken.
8076 if ((error = terminate_slave_thread(
1777 mi->info_thd, io_lock, &mi->stop_cond, &mi->slave_running,
1778
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 8076 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 8076 times.
8076 &total_stop_wait_timeout, need_lock_term, force_io_stop)) &&
1779 !force_all) {
1780 if (error == 1) {
1781 return ER_STOP_SLAVE_IO_THREAD_TIMEOUT;
1782 }
1783 return error;
1784 }
1785
1786 #ifndef NDEBUG
1787
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 8073 times.
8076 if (force_io_stop) {
1788
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 if (DBUG_EVALUATE_IF("simulate_io_thd_wait_for_disk_space", 1, 0)) {
1789
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 DBUG_SET("-d,simulate_io_thd_wait_for_disk_space");
1790 }
1791 }
1792 #endif
1793
1794
1/2
✓ Branch 0 taken 8076 times.
✗ Branch 1 not taken.
8076 mysql_mutex_lock(log_lock);
1795
1796
3/8
✓ Branch 0 taken 8076 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8076 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 8076 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
8076 DBUG_PRINT("info", ("Flushing relay log and source info repository."));
1797
3/4
✓ Branch 0 taken 8076 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6295 times.
✓ Branch 3 taken 1781 times.
8076 if (current_thd)
1798
2/4
✓ Branch 0 taken 6295 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6295 times.
✗ Branch 3 not taken.
6295 THD_STAGE_INFO(current_thd,
1799 stage_flushing_relay_log_and_source_info_repository);
1800
1801 /*
1802 Flushes the master info regardless of the sync_source_info option and
1803 GTID_ONLY = 0 for this channel
1804 */
1805
3/4
✓ Branch 0 taken 8076 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6791 times.
✓ Branch 3 taken 1285 times.
8076 if (!mi->is_gtid_only_mode()) {
1806
1/2
✓ Branch 0 taken 6791 times.
✗ Branch 1 not taken.
6791 mysql_mutex_lock(&mi->data_lock);
1807
3/4
✓ Branch 0 taken 6791 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 6790 times.
6791 if (mi->flush_info(true)) {
1808
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 mysql_mutex_unlock(&mi->data_lock);
1809
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 mysql_mutex_unlock(log_lock);
1810 1 return ER_ERROR_DURING_FLUSH_LOGS;
1811 }
1812
1/2
✓ Branch 0 taken 6790 times.
✗ Branch 1 not taken.
6790 mysql_mutex_unlock(&mi->data_lock);
1813 }
1814 /*
1815 Flushes the relay log regardless of the sync_relay_log option.
1816 */
1817
3/4
✓ Branch 0 taken 8065 times.
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8075 times.
16140 if (mi->rli->relay_log.is_open() &&
1818
2/4
✓ Branch 0 taken 8065 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 8065 times.
8065 mi->rli->relay_log.flush_and_sync(true)) {
1819 mysql_mutex_unlock(log_lock);
1820 return ER_ERROR_DURING_FLUSH_LOGS;
1821 }
1822
1823
1/2
✓ Branch 0 taken 8075 times.
✗ Branch 1 not taken.
8075 mysql_mutex_unlock(log_lock);
1824 }
1825 11024 return 0;
1826 17149 }
1827
1828 /**
1829 Wait for a slave thread to terminate.
1830
1831 This function is called after requesting the thread to terminate
1832 (by setting @c abort_slave member of @c Relay_log_info or @c
1833 Master_info structure to 1). Termination of the thread is
1834 controlled with the the predicate <code>*slave_running</code>.
1835
1836 Function will acquire @c term_lock before waiting on the condition
1837 unless @c need_lock_term is false in which case the mutex should be
1838 owned by the caller of this function and will remain acquired after
1839 return from the function.
1840
1841 @param thd
1842 Current session.
1843 @param term_lock
1844 Associated lock to use when waiting for @c term_cond
1845
1846 @param term_cond
1847 Condition that is signalled when the thread has terminated
1848
1849 @param slave_running
1850 Pointer to predicate to check for slave thread termination
1851
1852 @param stop_wait_timeout
1853 A pointer to a variable that denotes the time the thread has
1854 to stop before we time out and throw an error.
1855
1856 @param need_lock_term
1857 If @c false the lock will not be acquired before waiting on
1858 the condition. In this case, it is assumed that the calling
1859 function acquires the lock before calling this function.
1860
1861 @param force
1862 Force the slave thread to stop by sending a KILL_CONNECTION
1863 signal to it. This is used to forcefully stop the I/O thread
1864 when it is waiting for disk space and the server is shutting
1865 down.
1866
1867 @retval 0 All OK, 1 on "STOP SLAVE" command timeout,
1868 ER_SLAVE_CHANNEL_NOT_RUNNING otherwise.
1869
1870 @note If the executing thread has to acquire term_lock
1871 (need_lock_term is true, the negative running status does not
1872 represent any issue therefore no error is reported.
1873
1874 */
1875 18336 static int terminate_slave_thread(THD *thd, mysql_mutex_t *term_lock,
1876 mysql_cond_t *term_cond,
1877 std::atomic<uint> *slave_running,
1878 ulong *stop_wait_timeout, bool need_lock_term,
1879 bool force) {
1880
1/2
✓ Branch 0 taken 18336 times.
✗ Branch 1 not taken.
18336 DBUG_TRACE;
1881
2/2
✓ Branch 0 taken 3562 times.
✓ Branch 1 taken 14774 times.
18336 if (need_lock_term) {
1882
1/2
✓ Branch 0 taken 3562 times.
✗ Branch 1 not taken.
3562 mysql_mutex_lock(term_lock);
1883 } else {
1884 mysql_mutex_assert_owner(term_lock);
1885 }
1886
2/2
✓ Branch 0 taken 3228 times.
✓ Branch 1 taken 15108 times.
18336 if (!*slave_running) {
1887
1/2
✓ Branch 0 taken 3228 times.
✗ Branch 1 not taken.
3228 if (need_lock_term) {
1888 /*
1889 if run_lock (term_lock) is acquired locally then either
1890 slave_running status is fine
1891 */
1892
1/2
✓ Branch 0 taken 3228 times.
✗ Branch 1 not taken.
3228 mysql_mutex_unlock(term_lock);
1893 3228 return 0;
1894 } else {
1895 return ER_SLAVE_CHANNEL_NOT_RUNNING;
1896 }
1897 }
1898
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15108 times.
15108 assert(thd != nullptr);
1899
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15108 times.
15108 THD_CHECK_SENTRY(thd);
1900
1901 /*
1902 Is is critical to test if the slave is running. Otherwise, we might
1903 be referening freed memory trying to kick it
1904 */
1905
1906
2/2
✓ Branch 0 taken 15480 times.
✓ Branch 1 taken 15100 times.
30580 while (*slave_running) // Should always be true
1907 {
1908
3/8
✓ Branch 0 taken 15480 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15480 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 15480 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
15480 DBUG_PRINT("loop", ("killing slave thread"));
1909
1910
1/2
✓ Branch 0 taken 15480 times.
✗ Branch 1 not taken.
15480 mysql_mutex_lock(&thd->LOCK_thd_data);
1911 /*
1912 Error codes from pthread_kill are:
1913 EINVAL: invalid signal number (can't happen)
1914 ESRCH: thread already killed (can happen, should be ignored)
1915 */
1916 #ifndef _WIN32
1917 15480 int err [[maybe_unused]] = pthread_kill(thd->real_id, SIGALRM);
1918
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15480 times.
15480 assert(err != EINVAL);
1919 #endif
1920
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 15477 times.
15480 if (force)
1921
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 thd->awake(THD::KILL_CONNECTION);
1922 else
1923
1/2
✓ Branch 0 taken 15477 times.
✗ Branch 1 not taken.
15477 thd->awake(THD::NOT_KILLED);
1924
1/2
✓ Branch 0 taken 15480 times.
✗ Branch 1 not taken.
15480 mysql_mutex_unlock(&thd->LOCK_thd_data);
1925
1926
4/6
✓ Branch 0 taken 15480 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 15478 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
15480 DBUG_EXECUTE_IF("block_on_thread_stop_after_awake", {
1927 rpl_replica_debug_point(DBUG_RPL_R_WAIT_AFTER_AWAKE_ON_THREAD_STOP);
1928 });
1929
1930 /*
1931 There is a small chance that slave thread might miss the first
1932 alarm. To protect against it, resend the signal until it reacts
1933 */
1934 struct timespec abstime;
1935
1/2
✓ Branch 0 taken 15480 times.
✗ Branch 1 not taken.
15480 set_timespec(&abstime, 2);
1936 #ifndef NDEBUG
1937 int error =
1938 #endif
1939
1/2
✓ Branch 0 taken 15480 times.
✗ Branch 1 not taken.
15480 mysql_cond_timedwait(term_cond, term_lock, &abstime);
1940
2/2
✓ Branch 0 taken 15467 times.
✓ Branch 1 taken 13 times.
15480 if ((*stop_wait_timeout) >= 2)
1941 15467 (*stop_wait_timeout) = (*stop_wait_timeout) - 2;
1942
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 5 times.
13 else if (*slave_running) {
1943
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
8 if (need_lock_term) mysql_mutex_unlock(term_lock);
1944 8 return 1;
1945 }
1946
3/4
✓ Branch 0 taken 15100 times.
✓ Branch 1 taken 372 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 15100 times.
15472 assert(error == ETIMEDOUT || error == 0);
1947 }
1948
1949
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15100 times.
15100 assert(*slave_running == 0);
1950
1951
3/4
✓ Branch 0 taken 334 times.
✓ Branch 1 taken 14766 times.
✓ Branch 2 taken 334 times.
✗ Branch 3 not taken.
15100 if (need_lock_term) mysql_mutex_unlock(term_lock);
1952 15100 return 0;
1953 18336 }
1954
1955 17121 bool start_slave_thread(PSI_thread_key thread_key, my_start_routine h_func,
1956 mysql_mutex_t *start_lock, mysql_mutex_t *cond_lock,
1957 mysql_cond_t *start_cond,
1958 std::atomic<uint> *slave_running,
1959 std::atomic<ulong> *slave_run_id, Master_info *mi) {
1960 17121 bool is_error = false;
1961 17121 my_thread_handle th;
1962 ulong start_id;
1963
1/2
✓ Branch 0 taken 17121 times.
✗ Branch 1 not taken.
17121 DBUG_TRACE;
1964
1965
3/4
✓ Branch 0 taken 239 times.
✓ Branch 1 taken 16882 times.
✓ Branch 2 taken 239 times.
✗ Branch 3 not taken.
17121 if (start_lock) mysql_mutex_lock(start_lock);
1966
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 17115 times.
17121 if (!server_id) {
1967
2/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
6 if (start_cond) mysql_cond_broadcast(start_cond);
1968
9/18
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 6 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 6 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 6 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 6 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 6 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 6 times.
✗ Branch 17 not taken.
6 LogErr(ERROR_LEVEL, ER_RPL_SERVER_ID_MISSING, mi->get_for_channel_str());
1969
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 my_error(ER_BAD_SLAVE, MYF(0));
1970 6 goto err;
1971 }
1972
1973
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17115 times.
17115 if (*slave_running) {
1974 if (start_cond) mysql_cond_broadcast(start_cond);
1975 my_error(ER_SLAVE_CHANNEL_MUST_STOP, MYF(0), mi->get_channel());
1976 goto err;
1977 }
1978 17115 start_id = *slave_run_id;
1979
3/8
✓ Branch 0 taken 17115 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17115 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 17115 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
17115 DBUG_PRINT("info", ("Creating new slave thread"));
1980
2/4
✓ Branch 0 taken 17115 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 17115 times.
17115 if (mysql_thread_create(thread_key, &th, &connection_attrib, h_func,
1981 (void *)mi)) {
1982 LogErr(ERROR_LEVEL, ER_RPL_CANT_CREATE_SLAVE_THREAD,
1983 mi->get_for_channel_str());
1984 my_error(ER_SLAVE_THREAD, MYF(0));
1985 goto err;
1986 }
1987
3/4
✓ Branch 0 taken 16947 times.
✓ Branch 1 taken 168 times.
✓ Branch 2 taken 16947 times.
✗ Branch 3 not taken.
17115 if (start_cond && cond_lock) // caller has cond_lock
1988 {
1989
1/2
✓ Branch 0 taken 16947 times.
✗ Branch 1 not taken.
16947 THD *thd = current_thd;
1990
6/6
✓ Branch 0 taken 16947 times.
✓ Branch 1 taken 16876 times.
✓ Branch 2 taken 16876 times.
✓ Branch 3 taken 71 times.
✓ Branch 4 taken 16876 times.
✓ Branch 5 taken 16947 times.
33823 while (start_id == *slave_run_id && thd != nullptr) {
1991
3/8
✓ Branch 0 taken 16876 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16876 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 16876 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
16876 DBUG_PRINT("sleep", ("Waiting for replica thread to start"));
1992 16876 PSI_stage_info saved_stage = {0, "", 0, ""};
1993
1/2
✓ Branch 0 taken 16876 times.
✗ Branch 1 not taken.
16876 thd->ENTER_COND(start_cond, cond_lock,
1994 &stage_waiting_for_replica_thread_to_start, &saved_stage);
1995 /*
1996 It is not sufficient to test this at loop bottom. We must test
1997 it after registering the mutex in enter_cond(). If the kill
1998 happens after testing of thd->killed and before the mutex is
1999 registered, we could otherwise go waiting though thd->killed is
2000 set.
2001 */
2002
2/4
✓ Branch 0 taken 16876 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16876 times.
✗ Branch 3 not taken.
16876 if (!thd->killed) mysql_cond_wait(start_cond, cond_lock);
2003
1/2
✓ Branch 0 taken 16876 times.
✗ Branch 1 not taken.
16876 mysql_mutex_unlock(cond_lock);
2004
1/2
✓ Branch 0 taken 16876 times.
✗ Branch 1 not taken.
16876 thd->EXIT_COND(&saved_stage);
2005
1/2
✓ Branch 0 taken 16876 times.
✗ Branch 1 not taken.
16876 mysql_mutex_lock(cond_lock); // re-acquire it
2006
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16876 times.
16876 if (thd->killed) {
2007 my_error(thd->killed, MYF(0));
2008 goto err;
2009 }
2010 }
2011 }
2012
2013 17115 goto end;
2014 6 err:
2015 6 is_error = true;
2016 17121 end:
2017
2018
3/4
✓ Branch 0 taken 239 times.
✓ Branch 1 taken 16882 times.
✓ Branch 2 taken 239 times.
✗ Branch 3 not taken.
17121 if (start_lock) mysql_mutex_unlock(start_lock);
2019 17121 return is_error;
2020 17121 }
2021
2022 /*
2023 start_slave_threads()
2024
2025 NOTES
2026 SLAVE_FORCE_ALL is not implemented here on purpose since it does not make
2027 sense to do that for starting a slave--we always care if it actually
2028 started the threads that were not previously running
2029 */
2030
2031 10759 bool start_slave_threads(bool need_lock_slave, bool wait_for_start,
2032 Master_info *mi, int thread_mask) {
2033 10759 mysql_mutex_t *lock_io{nullptr}, *lock_sql{nullptr}, *lock_cond_io{nullptr},
2034 10759 *lock_cond_sql{nullptr};
2035 10759 mysql_cond_t *cond_io{nullptr}, *cond_sql{nullptr};
2036 10759 bool is_error{false};
2037
1/2
✓ Branch 0 taken 10759 times.
✗ Branch 1 not taken.
10759 DBUG_TRACE;
2038
2/4
✓ Branch 0 taken 10759 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10759 times.
10759 DBUG_EXECUTE_IF("uninitialized_source-info_structure", mi->inited = false;);
2039
2040
3/4
✓ Branch 0 taken 10759 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 10754 times.
10759 if (!mi->inited || !mi->rli->inited) {
2041
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 int error = (!mi->inited ? ER_SLAVE_MI_INIT_REPOSITORY
2042 : ER_SLAVE_RLI_INIT_REPOSITORY);
2043
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 Rpl_info *info = (!mi->inited ? mi : static_cast<Rpl_info *>(mi->rli));
2044
4/8
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5 times.
✗ Branch 7 not taken.
5 const char *prefix = current_thd ? ER_THD_NONCONST(current_thd, error)
2045 : ER_DEFAULT_NONCONST(error);
2046
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 info->report(ERROR_LEVEL,
2047
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 (!mi->inited ? ER_SERVER_SLAVE_MI_INIT_REPOSITORY
2048 : ER_SERVER_SLAVE_RLI_INIT_REPOSITORY),
2049 prefix, nullptr);
2050
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 my_error(error, MYF(0));
2051 5 return true;
2052 }
2053
2054
3/4
✓ Branch 0 taken 10754 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 10742 times.
10754 if (check_replica_configuration_errors(mi, thread_mask)) return true;
2055
2056 /**
2057 SQL AFTER MTS GAPS has no effect when GTID_MODE=ON and SOURCE_AUTO_POS=1
2058 as no gaps information was collected.
2059 **/
2060
7/8
✓ Branch 0 taken 10742 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5102 times.
✓ Branch 3 taken 5640 times.
✓ Branch 4 taken 4831 times.
✓ Branch 5 taken 271 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 10741 times.
15573 if (global_gtid_mode.get() == Gtid_mode::ON && mi->is_auto_position() &&
2061
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4830 times.
4831 mi->rli->until_condition == Relay_log_info::UNTIL_SQL_AFTER_MTS_GAPS) {
2062
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 if (current_thd) {
2063 1 push_warning_printf(
2064
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 current_thd, Sql_condition::SL_WARNING,
2065 ER_WARN_SQL_AFTER_MTS_GAPS_GAP_NOT_CALCULATED,
2066
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 ER_THD(current_thd, ER_WARN_SQL_AFTER_MTS_GAPS_GAP_NOT_CALCULATED),
2067 mi->get_channel());
2068 }
2069 }
2070
2071
2/2
✓ Branch 0 taken 84 times.
✓ Branch 1 taken 10658 times.
10742 if (need_lock_slave) {
2072 84 lock_io = &mi->run_lock;
2073 84 lock_sql = &mi->rli->run_lock;
2074 }
2075
2/2
✓ Branch 0 taken 10658 times.
✓ Branch 1 taken 84 times.
10742 if (wait_for_start) {
2076 10658 cond_io = &mi->start_cond;
2077 10658 cond_sql = &mi->rli->start_cond;
2078 10658 lock_cond_io = &mi->run_lock;
2079 10658 lock_cond_sql = &mi->rli->run_lock;
2080 }
2081
2082
2/2
✓ Branch 0 taken 7061 times.
✓ Branch 1 taken 3681 times.
10742 if (thread_mask & SLAVE_IO)
2083
1/2
✓ Branch 0 taken 7061 times.
✗ Branch 1 not taken.
7061 is_error = start_slave_thread(key_thread_replica_io, handle_slave_io,
2084 lock_io, lock_cond_io, cond_io,
2085 &mi->slave_running, &mi->slave_run_id, mi);
2086
2087
4/4
✓ Branch 0 taken 7059 times.
✓ Branch 1 taken 3681 times.
✓ Branch 2 taken 107 times.
✓ Branch 3 taken 6952 times.
17799 if (!is_error && (thread_mask & (SLAVE_IO | SLAVE_MONITOR)) &&
2088
4/4
✓ Branch 0 taken 10740 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 73 times.
✓ Branch 3 taken 10669 times.
28541 mi->is_source_connection_auto_failover() &&
2089
4/6
✓ Branch 0 taken 107 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 107 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 73 times.
✓ Branch 5 taken 34 times.
107 !Source_IO_monitor::get_instance()->is_monitoring_process_running()) {
2090
2/4
✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 73 times.
✗ Branch 3 not taken.
73 is_error = Source_IO_monitor::get_instance()->launch_monitoring_process(
2091 key_thread_replica_monitor_io);
2092
2093
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 73 times.
73 if (is_error)
2094 terminate_slave_threads(mi, thread_mask & (SLAVE_IO | SLAVE_MONITOR),
2095 rpl_stop_replica_timeout, need_lock_slave);
2096 }
2097
2098
4/4
✓ Branch 0 taken 10740 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 9989 times.
✓ Branch 3 taken 751 times.
10742 if (!is_error && (thread_mask & SLAVE_SQL)) {
2099 /*
2100 MTS-recovery gaps gathering is placed onto common execution path
2101 for either START-SLAVE and --skip-start-replica= 0
2102 */
2103
2/2
✓ Branch 0 taken 2720 times.
✓ Branch 1 taken 7269 times.
9989 if (mi->rli->recovery_parallel_workers != 0) {
2104
2/4
✓ Branch 0 taken 2720 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2720 times.
2720 if (mts_recovery_groups(mi->rli)) {
2105 is_error = true;
2106 my_error(ER_MTS_RECOVERY_FAILURE, MYF(0));
2107 }
2108 }
2109
1/2
✓ Branch 0 taken 9989 times.
✗ Branch 1 not taken.
9989 if (!is_error)
2110 9989 is_error = start_slave_thread(
2111 key_thread_replica_sql, handle_slave_sql, lock_sql, lock_cond_sql,
2112
1/2
✓ Branch 0 taken 9989 times.
✗ Branch 1 not taken.
9989 cond_sql, &mi->rli->slave_running, &mi->rli->slave_run_id, mi);
2113
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 9985 times.
9989 if (is_error)
2114
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 terminate_slave_threads(mi, thread_mask & (SLAVE_IO | SLAVE_MONITOR),
2115 rpl_stop_replica_timeout, need_lock_slave);
2116 }
2117 10742 return is_error;
2118 10759 }
2119
2120 /*
2121 Release slave threads at time of executing shutdown.
2122
2123 SYNOPSIS
2124 end_slave()
2125 */
2126
2127 8053 void end_slave() {
2128
1/2
✓ Branch 0 taken 8053 times.
✗ Branch 1 not taken.
8053 DBUG_TRACE;
2129
2130 8053 Master_info *mi = nullptr;
2131
2132 /*
2133 This is called when the server terminates, in close_connections().
2134 It terminates slave threads. However, some CHANGE MASTER etc may still be
2135 running presently. If a START SLAVE was in progress, the mutex lock below
2136 will make us wait until slave threads have started, and START SLAVE
2137 returns, then we terminate them here.
2138 */
2139
1/2
✓ Branch 0 taken 8053 times.
✗ Branch 1 not taken.
8053 channel_map.wrlock();
2140
2141 /* traverse through the map and terminate the threads */
2142
4/6
✓ Branch 0 taken 8053 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15950 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7897 times.
✓ Branch 5 taken 8053 times.
15950 for (mi_map::iterator it = channel_map.begin(); it != channel_map.end();
2143 7897 it++) {
2144 7897 mi = it->second;
2145
2146
1/2
✓ Branch 0 taken 7897 times.
✗ Branch 1 not taken.
7897 if (mi)
2147
1/2
✓ Branch 0 taken 7897 times.
✗ Branch 1 not taken.
7897 terminate_slave_threads(mi, SLAVE_FORCE_ALL, rpl_stop_replica_timeout);
2148 }
2149
1/2
✓ Branch 0 taken 8053 times.
✗ Branch 1 not taken.
8053 channel_map.unlock();
2150 8053 }
2151
2152 /**
2153 Free all resources used by slave threads at time of executing shutdown.
2154 The routine must be called after all possible users of channel_map
2155 have left.
2156
2157 */
2158 8048 void delete_slave_info_objects() {
2159
1/2
✓ Branch 0 taken 8048 times.
✗ Branch 1 not taken.
8048 DBUG_TRACE;
2160
2161 8048 Master_info *mi = nullptr;
2162
2163
1/2
✓ Branch 0 taken 8048 times.
✗ Branch 1 not taken.
8048 channel_map.wrlock();
2164
2165
4/6
✓ Branch 0 taken 8048 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15940 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7892 times.
✓ Branch 5 taken 8048 times.
15940 for (mi_map::iterator it = channel_map.begin(); it != channel_map.end();
2166 7892 it++) {
2167 7892 mi = it->second;
2168
2169
1/2
✓ Branch 0 taken 7892 times.
✗ Branch 1 not taken.
7892 if (mi) {
2170
1/2
✓ Branch 0 taken 7892 times.
✗ Branch 1 not taken.
7892 mi->channel_wrlock();
2171
1/2
✓ Branch 0 taken 7892 times.
✗ Branch 1 not taken.
7892 end_info(mi);
2172
2/4
✓ Branch 0 taken 7892 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7892 times.
✗ Branch 3 not taken.
7892 if (mi->rli) delete mi->rli;
2173
1/2
✓ Branch 0 taken 7892 times.
✗ Branch 1 not taken.
7892 delete mi;
2174 7892 it->second = 0;
2175 }
2176 }
2177
2178 // Clean other types of channel
2179
1/2
✓ Branch 0 taken 8048 times.
✗ Branch 1 not taken.
8048 for (mi_map::iterator it = channel_map.begin(GROUP_REPLICATION_CHANNEL);
2180
3/4
✓ Branch 0 taken 9565 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1517 times.
✓ Branch 3 taken 8048 times.
9565 it != channel_map.end(GROUP_REPLICATION_CHANNEL); it++) {
2181 1517 mi = it->second;
2182
2183
1/2
✓ Branch 0 taken 1517 times.
✗ Branch 1 not taken.
1517 if (mi) {
2184
1/2
✓ Branch 0 taken 1517 times.
✗ Branch 1 not taken.
1517 mi->channel_wrlock();
2185
1/2
✓ Branch 0 taken 1517 times.
✗ Branch 1 not taken.
1517 end_info(mi);
2186
2/4
✓ Branch 0 taken 1517 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1517 times.
✗ Branch 3 not taken.
1517 if (mi->rli) delete mi->rli;
2187
1/2
✓ Branch 0 taken 1517 times.
✗ Branch 1 not taken.
1517 delete mi;
2188 1517 it->second = 0;
2189 }
2190 }
2191
2192
1/2
✓ Branch 0 taken 8048 times.
✗ Branch 1 not taken.
8048 channel_map.unlock();
2193 8048 }
2194
2195 /**
2196 Check if multi-statement transaction mode and master and slave info
2197 repositories are set to table.
2198
2199 @param thd THD object
2200
2201 @retval true Success
2202 @retval false Failure
2203 */
2204 59528 static bool is_autocommit_off_and_infotables(THD *thd) {
2205
1/2
✓ Branch 0 taken 59528 times.
✗ Branch 1 not taken.
59528 DBUG_TRACE;
2206
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 56056 times.
56068 return (thd && thd->in_multi_stmt_transaction_mode() &&
2207 12 (opt_mi_repository_id == INFO_REPOSITORY_TABLE ||
2208 opt_rli_repository_id == INFO_REPOSITORY_TABLE))
2209
3/4
✓ Branch 0 taken 56068 times.
✓ Branch 1 taken 3460 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
115596 ? true
2210 59528 : false;
2211 59528 }
2212
2213 339 static bool monitor_io_replica_killed(THD *thd, Master_info *mi) {
2214 339 return Source_IO_monitor::get_instance()->is_monitor_killed(thd, mi);
2215 }
2216
2217 2722990 static bool io_slave_killed(THD *thd, Master_info *mi) {
2218
1/2
✓ Branch 0 taken 2722990 times.
✗ Branch 1 not taken.
2722990 DBUG_TRACE;
2219
2220
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2722990 times.
2722990 assert(mi->info_thd == thd);
2221
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2722990 times.
2722990 assert(mi->slave_running); // tracking buffer overrun
2222
5/6
✓ Branch 0 taken 2716261 times.
✓ Branch 1 taken 6729 times.
✓ Branch 2 taken 2716261 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 217 times.
✓ Branch 5 taken 2716044 times.
5445981 return mi->abort_slave || connection_events_loop_aborted() || thd->killed;
2223 2722990 }
2224
2225 /**
2226 The function analyzes a possible killed status and makes
2227 a decision whether to accept it or not.
2228 Normally upon accepting the sql thread goes to shutdown.
2229 In the event of deferring decision @c rli->last_event_start_time waiting
2230 timer is set to force the killed status be accepted upon its expiration.
2231
2232 Notice Multi-Threaded-Slave behaves similarly in that when it's being
2233 stopped and the current group of assigned events has not yet scheduled
2234 completely, Coordinator defers to accept to leave its read-distribute
2235 state. The above timeout ensures waiting won't last endlessly, and in
2236 such case an error is reported.
2237
2238 @param thd pointer to a THD instance
2239 @param rli pointer to Relay_log_info instance
2240
2241 @return true the killed status is recognized, false a possible killed
2242 status is deferred.
2243 */
2244 14314154 bool sql_slave_killed(THD *thd, Relay_log_info *rli) {
2245 14314154 bool is_parallel_warn = false;
2246
2247
1/2
✓ Branch 0 taken 14314156 times.
✗ Branch 1 not taken.
14314154 DBUG_TRACE;
2248
2249
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14314156 times.
14314156 assert(rli->info_thd == thd);
2250
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14314156 times.
14314156 assert(rli->slave_running == 1);
2251
2/2
✓ Branch 0 taken 74092 times.
✓ Branch 1 taken 14240064 times.
14314156 if (rli->sql_thread_kill_accepted) return true;
2252
5/8
✓ Branch 0 taken 14240064 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 14240063 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
14240064 DBUG_EXECUTE_IF("stop_when_mta_in_group", rli->abort_slave = 1;
2253 DBUG_SET("-d,stop_when_mta_in_group");
2254 DBUG_SET("-d,simulate_stop_when_mta_in_group");
2255 return false;);
2256
8/8
✓ Branch 0 taken 14239829 times.
✓ Branch 1 taken 233 times.
✓ Branch 2 taken 14239065 times.
✓ Branch 3 taken 764 times.
✓ Branch 4 taken 10111 times.
✓ Branch 5 taken 14228954 times.
✓ Branch 6 taken 11108 times.
✓ Branch 7 taken 14228954 times.
14240063 if (connection_events_loop_aborted() || thd->killed || rli->abort_slave) {
2257 11108 rli->sql_thread_kill_accepted = true;
2258 /* NOTE: In MTS mode if all workers are done and if the partial trx
2259 (if any) can be rolled back safely we can accept the kill */
2260 const bool cannot_rollback =
2261
3/4
✓ Branch 0 taken 11108 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1640 times.
✓ Branch 3 taken 9468 times.
12748 rli->is_mts_in_group() &&
2262
5/6
✓ Branch 0 taken 1624 times.
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 1624 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 327 times.
✓ Branch 5 taken 1297 times.
1640 (!rli->abort_slave || !rli->mts_workers_queue_empty() ||
2263
3/4
✓ Branch 0 taken 327 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 204 times.
✓ Branch 3 taken 123 times.
327 rli->cannot_safely_rollback());
2264
2265 11108 is_parallel_warn =
2266
7/8
✓ Branch 0 taken 11108 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11064 times.
✓ Branch 3 taken 44 times.
✓ Branch 4 taken 9547 times.
✓ Branch 5 taken 1517 times.
✓ Branch 6 taken 727 times.
✓ Branch 7 taken 8820 times.
11108 (rli->is_parallel_exec() && (cannot_rollback || thd->killed));
2267 /*
2268 Slave can execute stop being in one of two MTS or Single-Threaded mode.
2269 The modes define different criteria to accept the stop.
2270 In particular that relates to the concept of groupping.
2271 Killed Coordinator thread expects the worst so it warns on
2272 possible consistency issue.
2273 */
2274
8/10
✓ Branch 0 taken 8864 times.
✓ Branch 1 taken 2244 times.
✓ Branch 2 taken 8864 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 44 times.
✓ Branch 5 taken 8820 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 44 times.
✓ Branch 8 taken 2244 times.
✓ Branch 9 taken 8864 times.
11152 if (is_parallel_warn || (!rli->is_parallel_exec() &&
2275 44 thd->get_transaction()->cannot_safely_rollback(
2276 Transaction_ctx::SESSION) &&
2277 rli->is_in_group())) {
2278 2244 char msg_stopped[] =
2279 "... Slave SQL Thread stopped with incomplete event group "
2280 "having non-transactional changes. "
2281 "If the group consists solely of row-based events, you can try "
2282 "to restart the slave with --replica-exec-mode=IDEMPOTENT, which "
2283 "ignores duplicate key, key not found, and similar errors (see "
2284 "documentation for details).";
2285 2244 char msg_stopped_mts[] =
2286 "... The slave coordinator and worker threads are stopped, possibly "
2287 "leaving data in inconsistent state. A restart should "
2288 "restore consistency automatically, although using non-transactional "
2289 "storage for data or info tables or DDL queries could lead to "
2290 "problems. "
2291 "In such cases you have to examine your data (see documentation for "
2292 "details).";
2293
2294
2/2
✓ Branch 0 taken 1531 times.
✓ Branch 1 taken 713 times.
2244 if (rli->abort_slave) {
2295
3/8
✓ Branch 0 taken 1531 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1531 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1531 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
1531 DBUG_PRINT("info",
2296 ("Request to stop slave SQL Thread received while "
2297 "applying an MTS group or a group that "
2298 "has non-transactional "
2299 "changes; waiting for completion of the group ... "));
2300
2301 /*
2302 Slave sql thread shutdown in face of unfinished group modified
2303 Non-trans table is handled via a timer. The slave may eventually
2304 give out to complete the current group and in that case there
2305 might be issues at consequent slave restart, see the error message.
2306 WL#2975 offers a robust solution requiring to store the last exectuted
2307 event's coordinates along with the group's coordianates
2308 instead of waiting with @c last_event_start_time the timer.
2309 */
2310
2311
2/2
✓ Branch 0 taken 141 times.
✓ Branch 1 taken 1390 times.
1531 if (rli->last_event_start_time == 0)
2312 141 rli->last_event_start_time = time(nullptr);
2313 1531 rli->sql_thread_kill_accepted =
2314 1531 difftime(time(nullptr), rli->last_event_start_time) <=
2315 SLAVE_WAIT_GROUP_DONE
2316 1531 ? false
2317 : true;
2318
2319
5/8
✓ Branch 0 taken 1531 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1529 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
1531 DBUG_EXECUTE_IF("stop_replica_middle_group",
2320 DBUG_EXECUTE_IF("incomplete_group_in_relay_log",
2321 rli->sql_thread_kill_accepted =
2322 true;);); // time is over
2323
2324
4/4
✓ Branch 0 taken 1529 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 90 times.
✓ Branch 3 taken 1439 times.
1531 if (!rli->sql_thread_kill_accepted && !rli->reported_unsafe_warning) {
2325
2/4
✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 90 times.
✗ Branch 3 not taken.
90 rli->report(
2326 WARNING_LEVEL, 0,
2327 !is_parallel_warn
2328 ? "Request to stop slave SQL Thread received while "
2329 "applying a group that has non-transactional "
2330 "changes; waiting for completion of the group ... "
2331 : "Coordinator thread of multi-threaded slave is being "
2332 "stopped in the middle of assigning a group of events; "
2333 "deferring to exit until the group completion ... ");
2334 90 rli->reported_unsafe_warning = true;
2335 }
2336 }
2337
2/2
✓ Branch 0 taken 715 times.
✓ Branch 1 taken 1529 times.
2244 if (rli->sql_thread_kill_accepted) {
2338
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 697 times.
715 if (rli->mts_group_status == Relay_log_info::MTS_IN_GROUP) {
2339 18 rli->mts_group_status = Relay_log_info::MTS_KILLED_GROUP;
2340 }
2341
1/2
✓ Branch 0 taken 715 times.
✗ Branch 1 not taken.
715 if (is_parallel_warn)
2342
4/6
✓ Branch 0 taken 715 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 709 times.
✓ Branch 4 taken 715 times.
✗ Branch 5 not taken.
715 rli->report(!rli->is_error()
2343 ? ERROR_LEVEL
2344 : WARNING_LEVEL, // an error was reported by Worker
2345 ER_MTS_INCONSISTENT_DATA,
2346 ER_THD(thd, ER_MTS_INCONSISTENT_DATA), msg_stopped_mts);
2347 else
2348 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
2349 ER_THD(thd, ER_SLAVE_FATAL_ERROR), msg_stopped);
2350 }
2351 }
2352 }
2353
2354
2/2
✓ Branch 0 taken 9579 times.
✓ Branch 1 taken 14230483 times.
14240062 if (rli->sql_thread_kill_accepted) rli->last_event_start_time = 0;
2355
2356 14240062 return rli->sql_thread_kill_accepted;
2357 14314155 }
2358
2359 1245 bool net_request_file(NET *net, const char *fname) {
2360
1/2
✓ Branch 0 taken 1245 times.
✗ Branch 1 not taken.
1245 DBUG_TRACE;
2361
1/2
✓ Branch 0 taken 1245 times.
✗ Branch 1 not taken.
1245 return net_write_command(net, 251, pointer_cast<const uchar *>(fname),
2362 2490 strlen(fname), pointer_cast<const uchar *>(""), 0);
2363 1245 }
2364
2365 /*
2366 From other comments and tests in code, it looks like
2367 sometimes Query_log_event and Load_log_event can have db == 0
2368 (see rewrite_db() above for example)
2369 (cases where this happens are unclear; it may be when the master is 3.23).
2370 */
2371
2372 1696 const char *print_slave_db_safe(const char *db) {
2373
1/2
✓ Branch 0 taken 1696 times.
✗ Branch 1 not taken.
1696 DBUG_TRACE;
2374
2375
1/2
✓ Branch 0 taken 1696 times.
✗ Branch 1 not taken.
3392 return (db ? db : "");
2376 1696 }
2377
2378 6968 bool is_network_error(uint errorno) {
2379
3/4
✓ Branch 0 taken 6821 times.
✓ Branch 1 taken 147 times.
✓ Branch 2 taken 6821 times.
✗ Branch 3 not taken.
6968 return errorno == CR_CONNECTION_ERROR || errorno == CR_CONN_HOST_ERROR ||
2380
3/4
✓ Branch 0 taken 445 times.
✓ Branch 1 taken 6376 times.
✓ Branch 2 taken 445 times.
✗ Branch 3 not taken.
6821 errorno == CR_SERVER_GONE_ERROR || errorno == CR_SERVER_LOST ||
2381
3/4
✓ Branch 0 taken 445 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 440 times.
✓ Branch 3 taken 5 times.
445 errorno == ER_CON_COUNT_ERROR || errorno == ER_SERVER_SHUTDOWN ||
2382
2/4
✓ Branch 0 taken 6968 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 440 times.
13936 errorno == ER_NET_READ_INTERRUPTED ||
2383 6968 errorno == ER_NET_WRITE_INTERRUPTED;
2384 }
2385
2386 enum enum_command_status {
2387 COMMAND_STATUS_OK,
2388 COMMAND_STATUS_ERROR,
2389 COMMAND_STATUS_ALLOWED_ERROR
2390 };
2391 /**
2392 Execute an initialization query for the IO thread.
2393
2394 If there is an error, then this function calls mysql_free_result;
2395 otherwise the MYSQL object holds the result after this call. If
2396 there is an error other than allowed_error, then this function
2397 prints a message and returns -1.
2398
2399 @param mi Master_info object.
2400 @param query Query string.
2401 @param allowed_error Allowed error code, or 0 if no errors are allowed.
2402 @param[out] master_res If this is not NULL and there is no error, then
2403 mysql_store_result() will be called and the result stored in this pointer.
2404 @param[out] master_row If this is not NULL and there is no error, then
2405 mysql_fetch_row() will be called and the result stored in this pointer.
2406
2407 @retval COMMAND_STATUS_OK No error.
2408 @retval COMMAND_STATUS_ALLOWED_ERROR There was an error and the
2409 error code was 'allowed_error'.
2410 @retval COMMAND_STATUS_ERROR There was an error and the error code
2411 was not 'allowed_error'.
2412 */
2413 7199 static enum_command_status io_thread_init_command(
2414 Master_info *mi, const char *query, int allowed_error,
2415 MYSQL_RES **master_res = nullptr, MYSQL_ROW *master_row = nullptr) {
2416
1/2
✓ Branch 0 taken 7199 times.
✗ Branch 1 not taken.
7199 DBUG_TRACE;
2417
3/8
✓ Branch 0 taken 7199 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7199 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 7199 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
7199 DBUG_PRINT("info", ("IO thread initialization command: '%s'", query));
2418 7199 MYSQL *mysql = mi->mysql;
2419
1/2
✓ Branch 0 taken 7199 times.
✗ Branch 1 not taken.
7199 int ret = mysql_real_query(mysql, query, static_cast<ulong>(strlen(query)));
2420
2/4
✓ Branch 0 taken 7199 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7199 times.
7199 if (io_slave_killed(mi->info_thd, mi)) {
2421 LogErr(INFORMATION_LEVEL, ER_RPL_SLAVE_IO_THREAD_WAS_KILLED,
2422 mi->get_for_channel_str(), query);
2423 mysql_free_result(mysql_store_result(mysql));
2424 return COMMAND_STATUS_ERROR;
2425 }
2426
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7199 times.
7199 if (ret != 0) {
2427 uint err{mysql_errno(mysql)};
2428 mysql_free_result(mysql_store_result(mysql));
2429 if (is_network_error(err)) mi->set_network_error();
2430 if (!err || (int)err != allowed_error) {
2431 mi->report(is_network_error(err) ? WARNING_LEVEL : ERROR_LEVEL, err,
2432 "The slave IO thread stops because the initialization query "
2433 "'%s' failed with error '%s'.",
2434 query, mysql_error(mysql));
2435 return COMMAND_STATUS_ERROR;
2436 }
2437 return COMMAND_STATUS_ALLOWED_ERROR;
2438 }
2439
1/2
✓ Branch 0 taken 7199 times.
✗ Branch 1 not taken.
7199 if (master_res != nullptr) {
2440
2/4
✓ Branch 0 taken 7199 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7199 times.
7199 if ((*master_res = mysql_store_result(mysql)) == nullptr) {
2441 uint err{mysql_errno(mysql)};
2442 if (is_network_error(err)) mi->set_network_error();
2443 mi->report(WARNING_LEVEL, mysql_errno(mysql),
2444 "The slave IO thread stops because the initialization query "
2445 "'%s' did not return any result.",
2446 query);
2447 return COMMAND_STATUS_ERROR;
2448 }
2449
1/2
✓ Branch 0 taken 7199 times.
✗ Branch 1 not taken.
7199 if (master_row != nullptr) {
2450
2/4
✓ Branch 0 taken 7199 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7199 times.
7199 if ((*master_row = mysql_fetch_row(*master_res)) == nullptr) {
2451 uint err{mysql_errno(mysql)};
2452 if (is_network_error(err)) mi->set_network_error();
2453 mysql_free_result(*master_res);
2454 mi->report(WARNING_LEVEL, mysql_errno(mysql),
2455 "The slave IO thread stops because the initialization query "
2456 "'%s' did not return any row.",
2457 query);
2458 return COMMAND_STATUS_ERROR;
2459 }
2460 }
2461 } else
2462 assert(master_row == nullptr);
2463 7199 return COMMAND_STATUS_OK;
2464 7199 }
2465
2466 /**
2467 Set user variables after connecting to the master.
2468
2469 @param mysql MYSQL to request uuid from master.
2470 @param mi Master_info to set master_uuid
2471
2472 @return 0: Success, 1: Fatal error, 2: Transient network error.
2473 */
2474 7154 int io_thread_init_commands(MYSQL *mysql, Master_info *mi) {
2475 char query[256];
2476 7154 int ret = 0;
2477
3/4
✓ Branch 0 taken 7154 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 7152 times.
7154 DBUG_EXECUTE_IF("fake_5_5_version_replica", return ret;);
2478
2479 7152 mi->reset_network_error();
2480
2481 7152 sprintf(query, "SET @slave_uuid = '%s', @replica_uuid = '%s'", server_uuid,
2482 server_uuid);
2483
3/6
✓ Branch 0 taken 7151 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7151 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 7151 times.
7152 if (mysql_real_query(mysql, query, static_cast<ulong>(strlen(query))) &&
2484 !check_io_slave_killed(mi->info_thd, mi, nullptr))
2485 goto err;
2486
2487
2/4
✓ Branch 0 taken 7152 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7152 times.
✗ Branch 3 not taken.
7151 mysql_free_result(mysql_store_result(mysql));
2488 7152 return ret;
2489
2490 err:
2491 if (mysql_errno(mysql) && is_network_error(mysql_errno(mysql))) {
2492 mi->report(WARNING_LEVEL, mysql_errno(mysql),
2493 "The initialization command '%s' failed with the following"
2494 " error: '%s'.",
2495 query, mysql_error(mysql));
2496 mi->set_network_error();
2497 ret = 2;
2498 } else {
2499 char errmsg[512];
2500 const char *errmsg_fmt =
2501 "The slave I/O thread stops because a fatal error is encountered "
2502 "when it tries to send query to master(query: %s).";
2503
2504 sprintf(errmsg, errmsg_fmt, query);
2505 mi->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
2506 ER_THD(current_thd, ER_SLAVE_FATAL_ERROR), errmsg);
2507 ret = 1;
2508 }
2509 mysql_free_result(mysql_store_result(mysql));
2510 return ret;
2511 }
2512
2513 /**
2514 Get master's uuid on connecting.
2515
2516 @param mysql MYSQL to request uuid from master.
2517 @param mi Master_info to set master_uuid
2518
2519 @return 0: Success, 1: Fatal error, 2: Transient network error.
2520 */
2521 7156 static int get_master_uuid(MYSQL *mysql, Master_info *mi) {
2522 const char *errmsg;
2523 7156 MYSQL_RES *master_res = nullptr;
2524 7156 MYSQL_ROW master_row = nullptr;
2525 7156 int ret = 0;
2526 7156 char query_buf[] = "SELECT @@GLOBAL.SERVER_UUID";
2527
2528 7156 mi->reset_network_error();
2529
2530
3/4
✓ Branch 0 taken 7156 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 7155 times.
7156 DBUG_EXECUTE_IF("dbug.return_null_SOURCE_UUID", {
2531 mi->master_uuid[0] = 0;
2532 return 0;
2533 };);
2534
2535
4/6
✓ Branch 0 taken 7155 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 7151 times.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
7155 DBUG_EXECUTE_IF("dbug.before_get_SOURCE_UUID",
2536 { rpl_replica_debug_point(DBUG_RPL_S_BEFORE_MASTER_UUID); };);
2537
2538
2/6
✓ Branch 0 taken 7155 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7155 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
7155 DBUG_EXECUTE_IF("dbug.simulate_busy_io",
2539 { rpl_replica_debug_point(DBUG_RPL_S_SIMULATE_BUSY_IO); };);
2540 #ifndef NDEBUG
2541
3/4
✓ Branch 0 taken 7155 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 7154 times.
7155 DBUG_EXECUTE_IF("dbug.simulate_no_such_var_server_uuid", {
2542 query_buf[strlen(query_buf) - 1] = '_'; // corrupt the last char
2543 });
2544 #endif
2545
1/2
✓ Branch 0 taken 7155 times.
✗ Branch 1 not taken.
7155 if (!mysql_real_query(mysql, STRING_WITH_LEN(query_buf)) &&
2546
6/8
✓ Branch 0 taken 7153 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 7153 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7153 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 7153 times.
✓ Branch 7 taken 2 times.
14308 (master_res = mysql_store_result(mysql)) &&
2547
2/4
✓ Branch 0 taken 7153 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7153 times.
✗ Branch 3 not taken.
7153 (master_row = mysql_fetch_row(master_res))) {
2548
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 7145 times.
7153 if (!strcmp(::server_uuid, master_row[0]) &&
2549
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7 times.
8 !mi->rli->replicate_same_server_id) {
2550 1 errmsg =
2551 "The slave I/O thread stops because master and slave have equal "
2552 "MySQL server UUIDs; these UUIDs must be different for "
2553 "replication to work.";
2554
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 mi->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
2555
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 ER_THD(current_thd, ER_SLAVE_FATAL_ERROR), errmsg);
2556 // Fatal error
2557 1 ret = 1;
2558 } else {
2559
4/4
✓ Branch 0 taken 2608 times.
✓ Branch 1 taken 4544 times.
✓ Branch 2 taken 59 times.
✓ Branch 3 taken 2549 times.
7152 if (mi->master_uuid[0] != 0 && strcmp(mi->master_uuid, master_row[0]))
2560
8/16
✓ Branch 0 taken 59 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 59 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 59 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 59 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 59 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 59 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 59 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 59 times.
✗ Branch 15 not taken.
59 LogErr(WARNING_LEVEL, ER_RPL_SLAVE_MASTER_UUID_HAS_CHANGED,
2561 mi->master_uuid);
2562 7152 strncpy(mi->master_uuid, master_row[0], UUID_LENGTH);
2563 7152 mi->master_uuid[UUID_LENGTH] = 0;
2564 }
2565
3/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
2 } else if (mysql_errno(mysql) != ER_UNKNOWN_SYSTEM_VARIABLE) {
2566
3/6
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 if (is_network_error(mysql_errno(mysql))) {
2567
3/6
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 mi->report(WARNING_LEVEL, mysql_errno(mysql),
2568 "Get master SERVER_UUID failed with error: %s",
2569 mysql_error(mysql));
2570 1 mi->set_network_error();
2571 1 ret = 2;
2572 } else {
2573 /* Fatal error */
2574 errmsg =
2575 "The slave I/O thread stops because a fatal error is encountered "
2576 "when it tries to get the value of SERVER_UUID variable from master.";
2577 mi->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
2578 ER_THD(current_thd, ER_SLAVE_FATAL_ERROR), errmsg);
2579 ret = 1;
2580 }
2581 } else {
2582 1 mi->master_uuid[0] = 0;
2583
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 mi->report(
2584 WARNING_LEVEL, ER_UNKNOWN_SYSTEM_VARIABLE,
2585 "Unknown system variable 'SERVER_UUID' on master. "
2586 "A probable cause is that the variable is not supported on the "
2587 "master (version: %s), even though it is on the slave (version: %s)",
2588 mysql->server_version, server_version);
2589 }
2590
2591
3/4
✓ Branch 0 taken 7153 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 7153 times.
✗ Branch 3 not taken.
7155 if (master_res) mysql_free_result(master_res);
2592 7155 return ret;
2593 }
2594
2595 /*
2596 Note that we rely on the master's version (3.23, 4.0.14 etc) instead of
2597 relying on the binlog's version. This is not perfect: imagine an upgrade
2598 of the master without waiting that all slaves are in sync with the master;
2599 then a slave could be fooled about the binlog's format. This is what happens
2600 when people upgrade a 3.23 master to 4.0 without doing RESET MASTER: 4.0
2601 slaves are fooled. So we do this only to distinguish between 3.23 and more
2602 recent masters (it's too late to change things for 3.23).
2603
2604 RETURNS
2605 0 ok
2606 1 error
2607 2 transient network problem, the caller should try to reconnect
2608 */
2609
2610 7219 static int get_master_version_and_clock(MYSQL *mysql, Master_info *mi) {
2611 char err_buff[MAX_SLAVE_ERRMSG];
2612 7219 const char *errmsg = nullptr;
2613 7219 int err_code = 0;
2614 7219 int version_number = 0;
2615 7219 version_number = atoi(mysql->server_version);
2616
2617 7219 MYSQL_RES *master_res = nullptr;
2618 MYSQL_ROW master_row;
2619
1/2
✓ Branch 0 taken 7219 times.
✗ Branch 1 not taken.
7219 DBUG_TRACE;
2620
2621
2/4
✓ Branch 0 taken 7219 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7219 times.
7219 DBUG_EXECUTE_IF("unrecognized_source_version", { version_number = 1; };);
2622
2623 7219 mi->reset_network_error();
2624
2625
2/4
✓ Branch 0 taken 7219 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7219 times.
7219 if (!my_isdigit(&my_charset_bin, *mysql->server_version) ||
2626 version_number < 5) {
2627 errmsg = "Master reported unrecognized MySQL version";
2628 err_code = ER_SLAVE_FATAL_ERROR;
2629 sprintf(err_buff, ER_THD_NONCONST(current_thd, err_code), errmsg);
2630 goto err;
2631 }
2632
2633
1/2
✓ Branch 0 taken 7219 times.
✗ Branch 1 not taken.
7219 mysql_mutex_lock(mi->rli->relay_log.get_log_lock());
2634
1/2
✓ Branch 0 taken 7219 times.
✗ Branch 1 not taken.
7219 mysql_mutex_lock(&mi->data_lock);
2635
3/6
✓ Branch 0 taken 7219 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7219 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7219 times.
✗ Branch 5 not taken.
7219 mi->set_mi_description_event(new Format_description_log_event());
2636 /* as we are here, we tried to allocate the event */
2637
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7219 times.
7219 if (mi->get_mi_description_event() == nullptr) {
2638 mysql_mutex_unlock(&mi->data_lock);
2639 mysql_mutex_unlock(mi->rli->relay_log.get_log_lock());
2640 errmsg = "default Format_description_log_event";
2641 err_code = ER_SLAVE_CREATE_EVENT_FAILURE;
2642 sprintf(err_buff, ER_THD_NONCONST(current_thd, err_code), errmsg);
2643 goto err;
2644 }
2645
2646 /*
2647 FD_q's (A) is set initially from RL's (A): FD_q.(A) := RL.(A).
2648 It's necessary to adjust FD_q.(A) at this point because in the following
2649 course FD_q is going to be dumped to RL.
2650 Generally FD_q is derived from a received FD_m (roughly FD_q := FD_m)
2651 in queue_event and the master's (A) is installed.
2652 At one step with the assignment the Relay-Log's checksum alg is set to
2653 a new value: RL.(A) := FD_q.(A). If the slave service is stopped
2654 the last time assigned RL.(A) will be passed over to the restarting
2655 service (to the current execution point).
2656 RL.A is a "codec" to verify checksum in queue_event() almost all the time
2657 the first fake Rotate event.
2658 Starting from this point IO thread will executes the following checksum
2659 warmup sequence of actions:
2660
2661 FD_q.A := RL.A,
2662 A_m^0 := master.@@global.binlog_checksum,
2663 {queue_event(R_f): verifies(R_f, A_m^0)},
2664 {queue_event(FD_m): verifies(FD_m, FD_m.A), dump(FD_q), rotate(RL),
2665 FD_q := FD_m, RL.A := FD_q.A)}
2666
2667 See legends definition on MYSQL_BIN_LOG::relay_log_checksum_alg
2668 docs lines (binlog.h).
2669 In above A_m^0 - the value of master's
2670 @@binlog_checksum determined in the upcoming handshake (stored in
2671 mi->checksum_alg_before_fd).
2672
2673
2674 After the warm-up sequence IO gets to "normal" checksum verification mode
2675 to use RL.A in
2676
2677 {queue_event(E_m): verifies(E_m, RL.A)}
2678
2679 until it has received a new FD_m.
2680 */
2681 14438 mi->get_mi_description_event()->common_footer->checksum_alg =
2682 7219 mi->rli->relay_log.relay_log_checksum_alg;
2683
2684
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7219 times.
7219 assert(mi->get_mi_description_event()->common_footer->checksum_alg !=
2685 binary_log::BINLOG_CHECKSUM_ALG_UNDEF);
2686
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7219 times.
7219 assert(mi->rli->relay_log.relay_log_checksum_alg !=
2687 binary_log::BINLOG_CHECKSUM_ALG_UNDEF);
2688
2689
1/2
✓ Branch 0 taken 7219 times.
✗ Branch 1 not taken.
7219 mysql_mutex_unlock(&mi->data_lock);
2690
1/2
✓ Branch 0 taken 7219 times.
✗ Branch 1 not taken.
7219 mysql_mutex_unlock(mi->rli->relay_log.get_log_lock());
2691
2692 /*
2693 Compare the master and slave's clock. Do not die if master's clock is
2694 unavailable (very old master not supporting UNIX_TIMESTAMP()?).
2695 */
2696
2697
4/6
✓ Branch 0 taken 7219 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 7218 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
7219 DBUG_EXECUTE_IF("dbug.before_get_UNIX_TIMESTAMP", {
2698 rpl_replica_debug_point(DBUG_RPL_S_BEFORE_UNIX_TIMESTAMP);
2699 };);
2700
2701 7219 master_res = nullptr;
2702
5/8
✓ Branch 0 taken 7219 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 7218 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
7219 DBUG_EXECUTE_IF("get_master_version.timestamp.ER_NET_READ_INTERRUPTED", {
2703 DBUG_SET("+d,inject_ER_NET_READ_INTERRUPTED");
2704 DBUG_SET(
2705 "-d,get_master_version.timestamp."
2706 "ER_NET_READ_INTERRUPTED");
2707 });
2708
1/2
✓ Branch 0 taken 7219 times.
✗ Branch 1 not taken.
7219 if (!mysql_real_query(mysql, STRING_WITH_LEN("SELECT UNIX_TIMESTAMP()")) &&
2709
6/8
✓ Branch 0 taken 7217 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 7217 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7217 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 7217 times.
✓ Branch 7 taken 2 times.
14436 (master_res = mysql_store_result(mysql)) &&
2710
2/4
✓ Branch 0 taken 7217 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7217 times.
✗ Branch 3 not taken.
7217 (master_row = mysql_fetch_row(master_res))) {
2711
1/2
✓ Branch 0 taken 7217 times.
✗ Branch 1 not taken.
7217 mysql_mutex_lock(&mi->data_lock);
2712 7217 mi->clock_diff_with_master =
2713 7217 (long)(time((time_t *)nullptr) - strtoul(master_row[0], nullptr, 10));
2714
3/4
✓ Branch 0 taken 7217 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 7215 times.
7217 DBUG_EXECUTE_IF("dbug.mta.force_clock_diff_eq_0",
2715 mi->clock_diff_with_master = 0;);
2716
1/2
✓ Branch 0 taken 7217 times.
✗ Branch 1 not taken.
7217 mysql_mutex_unlock(&mi->data_lock);
2717
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 } else if (check_io_slave_killed(mi->info_thd, mi, nullptr))
2718 goto slave_killed_err;
2719
3/6
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
2 else if (is_network_error(mysql_errno(mysql))) {
2720
3/6
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
2 mi->report(WARNING_LEVEL, mysql_errno(mysql),
2721 "Get master clock failed with error: %s", mysql_error(mysql));
2722 2 goto network_err;
2723 } else {
2724 mysql_mutex_lock(&mi->data_lock);
2725 mi->clock_diff_with_master = 0; /* The "most sensible" value */
2726 mysql_mutex_unlock(&mi->data_lock);
2727 LogErr(WARNING_LEVEL, ER_RPL_SLAVE_SECONDS_BEHIND_MASTER_DUBIOUS,
2728 mysql_error(mysql), mysql_errno(mysql));
2729 }
2730
1/2
✓ Branch 0 taken 7217 times.
✗ Branch 1 not taken.
7217 if (master_res) {
2731
1/2
✓ Branch 0 taken 7217 times.
✗ Branch 1 not taken.
7217 mysql_free_result(master_res);
2732 7217 master_res = nullptr;
2733 }
2734
2735 /*
2736 Check that the master's server id and ours are different. Because if they
2737 are equal (which can result from a simple copy of master's datadir to slave,
2738 thus copying some my.cnf), replication will work but all events will be
2739 skipped.
2740 Do not die if SELECT @@SERVER_ID fails on master (very old master?).
2741 Note: we could have put a @@SERVER_ID in the previous SELECT
2742 UNIX_TIMESTAMP() instead, but this would not have worked on 3.23 masters.
2743 */
2744
4/6
✓ Branch 0 taken 7217 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 7216 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
7217 DBUG_EXECUTE_IF("dbug.before_get_SERVER_ID",
2745 { rpl_replica_debug_point(DBUG_RPL_S_BEFORE_SERVER_ID); };);
2746 7217 master_res = nullptr;
2747 7217 master_row = nullptr;
2748
5/8
✓ Branch 0 taken 7217 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 7216 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
7217 DBUG_EXECUTE_IF("get_source_server_id.ER_NET_READ_INTERRUPTED", {
2749 DBUG_SET("+d,inject_ER_NET_READ_INTERRUPTED");
2750 DBUG_SET(
2751 "-d,get_source_server_id."
2752 "ER_NET_READ_INTERRUPTED");
2753 });
2754
1/2
✓ Branch 0 taken 7217 times.
✗ Branch 1 not taken.
7217 if (!mysql_real_query(mysql, STRING_WITH_LEN("SELECT @@GLOBAL.SERVER_ID")) &&
2755
6/8
✓ Branch 0 taken 7215 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 7215 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7215 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 7215 times.
✓ Branch 7 taken 2 times.
14432 (master_res = mysql_store_result(mysql)) &&
2756
2/4
✓ Branch 0 taken 7215 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7215 times.
✗ Branch 3 not taken.
7215 (master_row = mysql_fetch_row(master_res))) {
2757 14430 if ((::server_id ==
2758
4/4
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 7201 times.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 7207 times.
7229 (mi->master_id = strtoul(master_row[0], nullptr, 10))) &&
2759
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 6 times.
14 !mi->rli->replicate_same_server_id) {
2760 8 errmsg =
2761 "The slave I/O thread stops because master and slave have equal "
2762 "MySQL server ids; these ids must be different for replication to "
2763 "work (or the --replicate-same-server-id option must be used on "
2764 "slave but this does not always make sense; please check the "
2765 "manual before using it).";
2766 8 err_code = ER_SLAVE_FATAL_ERROR;
2767
2/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
8 sprintf(err_buff, ER_THD(current_thd, ER_SLAVE_FATAL_ERROR), errmsg);
2768 8 goto err;
2769 }
2770
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 } else if (mysql_errno(mysql) != ER_UNKNOWN_SYSTEM_VARIABLE) {
2771
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (check_io_slave_killed(mi->info_thd, mi, nullptr))
2772 goto slave_killed_err;
2773
3/6
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
2 else if (is_network_error(mysql_errno(mysql))) {
2774
3/6
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
2 mi->report(WARNING_LEVEL, mysql_errno(mysql),
2775 "Get master SERVER_ID failed with error: %s",
2776 mysql_error(mysql));
2777 2 goto network_err;
2778 }
2779 /* Fatal error */
2780 errmsg =
2781 "The slave I/O thread stops because a fatal error is encountered "
2782 "when it try to get the value of SERVER_ID variable from master.";
2783 err_code = mysql_errno(mysql);
2784 sprintf(err_buff, "%s Error: %s", errmsg, mysql_error(mysql));
2785 goto err;
2786 } else {
2787 mi->report(WARNING_LEVEL, ER_SERVER_UNKNOWN_SYSTEM_VARIABLE,
2788 "Unknown system variable 'SERVER_ID' on master, maybe it "
2789 "is a *VERY OLD MASTER*.");
2790 }
2791
1/2
✓ Branch 0 taken 7207 times.
✗ Branch 1 not taken.
7207 if (master_res) {
2792
1/2
✓ Branch 0 taken 7207 times.
✗ Branch 1 not taken.
7207 mysql_free_result(master_res);
2793 7207 master_res = nullptr;
2794 }
2795
2/8
✗ Branch 0 not taken.
✓ Branch 1 taken 7207 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 7207 times.
7207 if (mi->master_id == 0 && mi->ignore_server_ids->dynamic_ids.size() > 0) {
2796 errmsg =
2797 "Slave configured with server id filtering could not detect the master "
2798 "server id.";
2799 err_code = ER_SLAVE_FATAL_ERROR;
2800 sprintf(err_buff, ER_THD(current_thd, ER_SLAVE_FATAL_ERROR), errmsg);
2801 goto err;
2802 }
2803
2804
2/2
✓ Branch 0 taken 7206 times.
✓ Branch 1 taken 1 times.
7207 if (mi->heartbeat_period != 0.0) {
2805 char llbuf[22];
2806 7206 const char query_format[] =
2807 "SET @master_heartbeat_period = %s, @source_heartbeat_period = %s";
2808 char query[sizeof(query_format) - 2 * 2 + 2 * sizeof(llbuf) + 1];
2809 /*
2810 the period is an ulonglong of nano-secs.
2811 */
2812
1/2
✓ Branch 0 taken 7206 times.
✗ Branch 1 not taken.
7206 llstr((ulonglong)(mi->heartbeat_period * 1000000000UL), llbuf);
2813 7206 sprintf(query, query_format, llbuf, llbuf);
2814
2815
5/8
✓ Branch 0 taken 7206 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 7203 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
7206 DBUG_EXECUTE_IF("get_master_version.heartbeat.ER_NET_READ_INTERRUPTED", {
2816 DBUG_SET("+d,inject_ER_NET_READ_INTERRUPTED");
2817 DBUG_SET(
2818 "-d,get_master_version.heartbeat."
2819 "ER_NET_READ_INTERRUPTED");
2820 });
2821
2822
3/4
✓ Branch 0 taken 7206 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 7203 times.
7206 if (mysql_real_query(mysql, query, static_cast<ulong>(strlen(query)))) {
2823
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
3 if (check_io_slave_killed(mi->info_thd, mi, nullptr))
2824 goto slave_killed_err;
2825
2826
3/6
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
3 if (is_network_error(mysql_errno(mysql))) {
2827
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 mi->report(
2828
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 WARNING_LEVEL, mysql_errno(mysql),
2829 "SET @master_heartbeat_period to master failed with error: %s",
2830 mysql_error(mysql));
2831
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 mysql_free_result(mysql_store_result(mysql));
2832 3 goto network_err;
2833 } else {
2834 /* Fatal error */
2835 errmsg =
2836 "The slave I/O thread stops because a fatal error is encountered "
2837 " when it tries to SET @master_heartbeat_period on master.";
2838 err_code = ER_SLAVE_FATAL_ERROR;
2839 sprintf(err_buff, "%s Error: %s", errmsg, mysql_error(mysql));
2840 mysql_free_result(mysql_store_result(mysql));
2841 goto err;
2842 }
2843 }
2844
2/4
✓ Branch 0 taken 7203 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7203 times.
✗ Branch 3 not taken.
7203 mysql_free_result(mysql_store_result(mysql));
2845 }
2846
2847 /*
2848 Querying if master is capable to checksum and notifying it about own
2849 CRC-awareness. The master's side instant value of @@global.binlog_checksum
2850 is stored in the dump thread's uservar area as well as cached locally
2851 to become known in consensus by master and slave.
2852 */
2853
3/4
✓ Branch 0 taken 7204 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7203 times.
✓ Branch 3 taken 1 times.
7204 if (DBUG_EVALUATE_IF("simulate_replica_unaware_checksum", 0, 1)) {
2854 int rc;
2855 // Set both variables, so that it works equally on both old and new
2856 // source server.
2857 7203 const char query[] =
2858 "SET @master_binlog_checksum = @@global.binlog_checksum, "
2859 "@source_binlog_checksum = @@global.binlog_checksum";
2860 7203 master_res = nullptr;
2861 // initially undefined
2862 7203 mi->checksum_alg_before_fd = binary_log::BINLOG_CHECKSUM_ALG_UNDEF;
2863 /*
2864 @c checksum_alg_before_fd is queried from master in this block.
2865 If master is old checksum-unaware the value stays undefined.
2866 Once the first FD will be received its alg descriptor will replace
2867 the being queried one.
2868 */
2869
1/2
✓ Branch 0 taken 7203 times.
✗ Branch 1 not taken.
7203 rc = mysql_real_query(mysql, query, static_cast<ulong>(strlen(query)));
2870
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7203 times.
7203 if (rc != 0) {
2871 mi->checksum_alg_before_fd = binary_log::BINLOG_CHECKSUM_ALG_OFF;
2872 if (check_io_slave_killed(mi->info_thd, mi, nullptr))
2873 2 goto slave_killed_err;
2874
2875 if (mysql_errno(mysql) == ER_UNKNOWN_SYSTEM_VARIABLE) {
2876 // this is tolerable as OM -> NS is supported
2877 mi->report(WARNING_LEVEL, mysql_errno(mysql),
2878 "Notifying master by %s failed with "
2879 "error: %s",
2880 query, mysql_error(mysql));
2881 } else {
2882 if (is_network_error(mysql_errno(mysql))) {
2883 mi->report(WARNING_LEVEL, mysql_errno(mysql),
2884 "Notifying master by %s failed with "
2885 "error: %s",
2886 query, mysql_error(mysql));
2887 mysql_free_result(mysql_store_result(mysql));
2888 goto network_err;
2889 } else {
2890 errmsg =
2891 "The slave I/O thread stops because a fatal error is encountered "
2892 "when it tried to SET @master_binlog_checksum on master.";
2893 err_code = ER_SLAVE_FATAL_ERROR;
2894 sprintf(err_buff, "%s Error: %s", errmsg, mysql_error(mysql));
2895 mysql_free_result(mysql_store_result(mysql));
2896 3 goto err;
2897 }
2898 }
2899 } else {
2900
2/4
✓ Branch 0 taken 7203 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7203 times.
✗ Branch 3 not taken.
7203 mysql_free_result(mysql_store_result(mysql));
2901 // Read back the user variable that we just set, to verify that
2902 // the source recognized the checksum algorithm.
2903
1/2
✓ Branch 0 taken 7203 times.
✗ Branch 1 not taken.
7203 if (!mysql_real_query(
2904 7201 mysql, STRING_WITH_LEN("SELECT @source_binlog_checksum")) &&
2905
2/4
✓ Branch 0 taken 7201 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7201 times.
✗ Branch 3 not taken.
7201 (master_res = mysql_store_result(mysql)) &&
2906
6/8
✓ Branch 0 taken 7201 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 7201 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7201 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 7201 times.
✓ Branch 7 taken 2 times.
21605 (master_row = mysql_fetch_row(master_res)) &&
2907
1/2
✓ Branch 0 taken 7201 times.
✗ Branch 1 not taken.
7201 (master_row[0] != nullptr)) {
2908 7201 mi->checksum_alg_before_fd = static_cast<enum_binlog_checksum_alg>(
2909
1/2
✓ Branch 0 taken 7201 times.
✗ Branch 1 not taken.
7201 find_type(master_row[0], &binlog_checksum_typelib, 1) - 1);
2910
2911
3/4
✓ Branch 0 taken 7201 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 7198 times.
7201 DBUG_EXECUTE_IF("undefined_algorithm_on_replica",
2912 mi->checksum_alg_before_fd =
2913 binary_log::BINLOG_CHECKSUM_ALG_UNDEF;);
2914
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 7198 times.
7201 if (mi->checksum_alg_before_fd ==
2915 binary_log::BINLOG_CHECKSUM_ALG_UNDEF) {
2916 3 errmsg =
2917 "The slave I/O thread was stopped because a fatal error is "
2918 "encountered "
2919 "The checksum algorithm used by master is unknown to slave.";
2920 3 err_code = ER_SLAVE_FATAL_ERROR;
2921
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 sprintf(err_buff, "%s Error: %s", errmsg, mysql_error(mysql));
2922
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 mysql_free_result(mysql_store_result(mysql));
2923 3 goto err;
2924 }
2925
2926 // valid outcome is either of
2927
3/4
✓ Branch 0 taken 7188 times.
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7188 times.
7198 assert(mi->checksum_alg_before_fd ==
2928 binary_log::BINLOG_CHECKSUM_ALG_OFF ||
2929 mi->checksum_alg_before_fd ==
2930 binary_log::BINLOG_CHECKSUM_ALG_CRC32);
2931
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 } else if (check_io_slave_killed(mi->info_thd, mi, nullptr))
2932 2 goto slave_killed_err;
2933 else if (is_network_error(mysql_errno(mysql))) {
2934 mi->report(WARNING_LEVEL, mysql_errno(mysql),
2935 "Get master BINLOG_CHECKSUM failed with error: %s",
2936 mysql_error(mysql));
2937 goto network_err;
2938 } else {
2939 errmsg =
2940 "The slave I/O thread stops because a fatal error is encountered "
2941 "when it tried to SELECT @master_binlog_checksum.";
2942 err_code = ER_SLAVE_FATAL_ERROR;
2943 sprintf(err_buff, "%s Error: %s", errmsg, mysql_error(mysql));
2944 mysql_free_result(mysql_store_result(mysql));
2945 goto err;
2946 }
2947 }
2948
1/2
✓ Branch 0 taken 7198 times.
✗ Branch 1 not taken.
7198 if (master_res) {
2949
1/2
✓ Branch 0 taken 7198 times.
✗ Branch 1 not taken.
7198 mysql_free_result(master_res);
2950 7198 master_res = nullptr;
2951 }
2952 } else
2953 1 mi->checksum_alg_before_fd = binary_log::BINLOG_CHECKSUM_ALG_OFF;
2954
2955
2/4
✓ Branch 0 taken 7199 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7199 times.
7199 if (DBUG_EVALUATE_IF("bug32442749_simulate_null_checksum", 1, 0)) {
2956 const char query[] = "SET @source_binlog_checksum= NULL";
2957 int rc = mysql_real_query(mysql, query, static_cast<ulong>(strlen(query)));
2958 if (rc != 0) {
2959 errmsg =
2960 "The slave I/O thread stops because a fatal error is encountered "
2961 "when it tried to SET @source_binlog_checksum.";
2962 err_code = ER_SLAVE_FATAL_ERROR;
2963 sprintf(err_buff, "%s Error: %s", errmsg, mysql_error(mysql));
2964 mysql_free_result(mysql_store_result(mysql));
2965 goto err;
2966 }
2967 mysql_free_result(mysql_store_result(mysql));
2968 }
2969
2970
2/4
✓ Branch 0 taken 7199 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7199 times.
✗ Branch 3 not taken.
7199 if (DBUG_EVALUATE_IF("simulate_replica_unaware_gtid", 0, 1)) {
2971 7199 auto master_gtid_mode = Gtid_mode::OFF;
2972
1/2
✓ Branch 0 taken 7199 times.
✗ Branch 1 not taken.
7199 auto slave_gtid_mode = global_gtid_mode.get();
2973
2/6
✓ Branch 0 taken 7199 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 7199 times.
✗ Branch 5 not taken.
7199 switch (io_thread_init_command(mi, "SELECT @@GLOBAL.GTID_MODE",
2974 ER_UNKNOWN_SYSTEM_VARIABLE, &master_res,
2975 &master_row)) {
2976 case COMMAND_STATUS_ERROR:
2977 43 return 2;
2978 case COMMAND_STATUS_ALLOWED_ERROR:
2979 // master is old and does not have @@GLOBAL.GTID_MODE
2980 master_gtid_mode = Gtid_mode::OFF;
2981 break;
2982 7199 case COMMAND_STATUS_OK: {
2983 7199 const char *master_gtid_mode_string = master_row[0];
2984
2/4
✓ Branch 0 taken 7199 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7199 times.
7199 DBUG_EXECUTE_IF("simulate_source_has_gtid_mode_on_something",
2985 { master_gtid_mode_string = "on_something"; });
2986
2/4
✓ Branch 0 taken 7199 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7199 times.
7199 DBUG_EXECUTE_IF("simulate_source_has_gtid_mode_off_something",
2987 { master_gtid_mode_string = "off_something"; });
2988
3/4
✓ Branch 0 taken 7199 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 7196 times.
7199 DBUG_EXECUTE_IF("simulate_source_has_unknown_gtid_mode",
2989 { master_gtid_mode_string = "Krakel Spektakel"; });
2990 bool error;
2991 7199 std::tie(error, master_gtid_mode) =
2992
2/4
✓ Branch 0 taken 7199 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7199 times.
✗ Branch 3 not taken.
14398 Gtid_mode::from_string(master_gtid_mode_string);
2993
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 7196 times.
7199 if (error) {
2994
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 mi->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
2995 "The slave IO thread stops because the master has "
2996 "an unknown @@GLOBAL.GTID_MODE '%s'.",
2997 master_gtid_mode_string);
2998
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 mysql_free_result(master_res);
2999 3 return 1;
3000 }
3001
1/2
✓ Branch 0 taken 7196 times.
✗ Branch 1 not taken.
7196 mysql_free_result(master_res);
3002 7196 break;
3003 }
3004 }
3005 11793 if ((slave_gtid_mode == Gtid_mode::OFF &&
3006
8/8
✓ Branch 0 taken 4597 times.
✓ Branch 1 taken 2599 times.
✓ Branch 2 taken 4591 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 2548 times.
✓ Branch 5 taken 4642 times.
✓ Branch 6 taken 19 times.
✓ Branch 7 taken 7177 times.
9744 master_gtid_mode >= Gtid_mode::ON_PERMISSIVE) ||
3007 2548 (slave_gtid_mode == Gtid_mode::ON &&
3008
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 2516 times.
2548 master_gtid_mode <= Gtid_mode::OFF_PERMISSIVE &&
3009
3/4
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 19 times.
32 mi->rli->m_assign_gtids_to_anonymous_transactions_info.get_type() ==
3010 Assign_gtids_to_anonymous_transactions_info::enum_type::
3011 AGAT_OFF)) {
3012
3/6
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 19 times.
✗ Branch 5 not taken.
19 mi->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
3013 "The replication receiver thread cannot start because "
3014 "the master has GTID_MODE = %.192s and this server has "
3015 "GTID_MODE = %.192s.",
3016 Gtid_mode::to_string(master_gtid_mode),
3017 Gtid_mode::to_string(slave_gtid_mode));
3018 19 return 1;
3019 }
3020
6/6
✓ Branch 0 taken 2338 times.
✓ Branch 1 taken 4839 times.
✓ Branch 2 taken 21 times.
✓ Branch 3 taken 2317 times.
✓ Branch 4 taken 21 times.
✓ Branch 5 taken 7156 times.
7177 if (mi->is_auto_position() && master_gtid_mode != Gtid_mode::ON) {
3021
2/4
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
✗ Branch 3 not taken.
21 mi->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
3022 "The replication receiver thread cannot start in "
3023 "AUTO_POSITION mode: the master has GTID_MODE = %.192s "
3024 "instead of ON.",
3025 Gtid_mode::to_string(master_gtid_mode));
3026 21 return 1;
3027 }
3028 }
3029
3030 err:
3031
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 7156 times.
7167 if (errmsg) {
3032
2/4
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
11 if (master_res) mysql_free_result(master_res);
3033
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 assert(err_code != 0);
3034
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 mi->report(ERROR_LEVEL, err_code, "%s", err_buff);
3035 11 return 1;
3036 }
3037
3038 7156 return 0;
3039
3040 7 network_err:
3041
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
7 if (master_res) mysql_free_result(master_res);
3042 7 mi->set_network_error();
3043 7 return 2;
3044
3045 2 slave_killed_err:
3046
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2 if (master_res) mysql_free_result(master_res);
3047 2 return 2;
3048 7219 }
3049
3050 73 static bool wait_for_relay_log_space(Relay_log_info *rli) {
3051 73 bool slave_killed = false;
3052 73 Master_info *mi = rli->mi;
3053 73 PSI_stage_info old_stage;
3054 73 THD *thd = mi->info_thd;
3055
1/2
✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
73 DBUG_TRACE;
3056
3057
1/2
✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
73 mysql_mutex_lock(&rli->log_space_lock);
3058
1/2
✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
73 thd->ENTER_COND(&rli->log_space_cond, &rli->log_space_lock,
3059 &stage_waiting_for_relay_log_space, &old_stage);
3060 73 while (rli->log_space_limit < rli->log_space_total &&
3061
7/8
✓ Branch 0 taken 160 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 160 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 157 times.
✓ Branch 5 taken 3 times.
✓ Branch 6 taken 89 times.
✓ Branch 7 taken 73 times.
319 !(slave_killed = io_slave_killed(thd, mi)) &&
3062
2/2
✓ Branch 0 taken 89 times.
✓ Branch 1 taken 68 times.
157 !rli->ignore_log_space_limit)
3063
1/2
✓ Branch 0 taken 89 times.
✗ Branch 1 not taken.
89 mysql_cond_wait(&rli->log_space_cond, &rli->log_space_lock);
3064
3065 /*
3066 Makes the IO thread read only one event at a time
3067 until the SQL thread is able to purge the relay
3068 logs, freeing some space.
3069
3070 Therefore, once the SQL thread processes this next
3071 event, it goes to sleep (no more events in the queue),
3072 sets ignore_log_space_limit=true and wakes the IO thread.
3073 However, this event may have been enough already for
3074 the SQL thread to purge some log files, freeing
3075 rli->log_space_total .
3076
3077 This guarantees that the SQL and IO thread move
3078 forward only one event at a time (to avoid deadlocks),
3079 when the relay space limit is reached. It also
3080 guarantees that when the SQL thread is prepared to
3081 rotate (to be able to purge some logs), the IO thread
3082 will know about it and will rotate.
3083
3084 NOTE: The ignore_log_space_limit is only set when the SQL
3085 thread sleeps waiting for events.
3086
3087 */
3088
2/2
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 5 times.
73 if (rli->ignore_log_space_limit) {
3089 #ifndef NDEBUG
3090 {
3091 char llbuf1[22], llbuf2[22];
3092
3/12
✓ Branch 0 taken 68 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 68 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 68 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
68 DBUG_PRINT("info", ("log_space_limit=%s "
3093 "log_space_total=%s "
3094 "ignore_log_space_limit=%d "
3095 "sql_force_rotate_relay=%d",
3096 llstr(rli->log_space_limit, llbuf1),
3097 llstr(rli->log_space_total, llbuf2),
3098 (int)rli->ignore_log_space_limit,
3099 (int)rli->sql_force_rotate_relay));
3100 }
3101 #endif
3102
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 43 times.
68 if (rli->sql_force_rotate_relay) {
3103
4/6
✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 22 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
25 DBUG_EXECUTE_IF("rpl_before_forced_rotate", {
3104 rpl_replica_debug_point(DBUG_RPL_S_BEFORE_FORCED_ROTATE);
3105 });
3106
1/2
✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
25 rotate_relay_log(mi, true, true, false);
3107 25 rli->sql_force_rotate_relay = false;
3108 }
3109
3110 68 rli->ignore_log_space_limit = false;
3111 }
3112
3113
1/2
✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
73 mysql_mutex_unlock(&rli->log_space_lock);
3114
1/2
✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
73 thd->EXIT_COND(&old_stage);
3115 73 return slave_killed;
3116 73 }
3117
3118 /*
3119 Builds a Rotate and writes it to relay log.
3120
3121 The caller must hold mi->data_lock.
3122
3123 @param thd pointer to I/O Thread's Thd.
3124 @param mi point to I/O Thread metadata class.
3125 @param force_flush_mi_info when true, do not respect sync period and flush
3126 information.
3127 when false, flush will only happen if it is time to
3128 flush.
3129
3130 @return 0 if everything went fine, 1 otherwise.
3131 */
3132 11667 static int write_rotate_to_master_pos_into_relay_log(THD *thd, Master_info *mi,
3133 bool force_flush_mi_info) {
3134 11667 Relay_log_info *rli = mi->rli;
3135 11667 int error = 0;
3136
1/2
✓ Branch 0 taken 11667 times.
✗ Branch 1 not taken.
11667 DBUG_TRACE;
3137
3138
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11667 times.
11667 assert(thd == mi->info_thd);
3139 mysql_mutex_assert_owner(rli->relay_log.get_log_lock());
3140
3141
3/8
✓ Branch 0 taken 11667 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11667 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 11667 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
11667 DBUG_PRINT("info", ("writing a Rotate event to the relay log"));
3142 11667 Rotate_log_event *ev = new Rotate_log_event(mi->get_master_log_name(), 0,
3143 11667 mi->get_master_log_pos(),
3144
2/4
✓ Branch 0 taken 11667 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11667 times.
✗ Branch 3 not taken.
11667 Rotate_log_event::DUP_NAME);
3145
3146
5/8
✓ Branch 0 taken 11667 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 11666 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
11667 DBUG_EXECUTE_IF("fail_generating_rotate_event_on_write_rotate_to_source_pos",
3147 {
3148 if (likely((bool)ev)) {
3149 delete ev;
3150 ev = nullptr;
3151 }
3152 });
3153
3154
2/2
✓ Branch 0 taken 11666 times.
✓ Branch 1 taken 1 times.
11667 if (likely((bool)ev)) {
3155
1/2
✓ Branch 0 taken 11666 times.
✗ Branch 1 not taken.
11666 if (mi->get_mi_description_event() != nullptr)
3156 11666 ev->common_footer->checksum_alg =
3157 11666 mi->get_mi_description_event()->common_footer->checksum_alg;
3158
3159 11666 ev->server_id = 0; // don't be ignored by slave SQL thread
3160
4/6
✓ Branch 0 taken 11666 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11666 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 11665 times.
11666 if (unlikely(rli->relay_log.write_event(ev, mi) != 0))
3161
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 mi->report(ERROR_LEVEL, ER_SLAVE_RELAY_LOG_WRITE_FAILURE,
3162 ER_THD(thd, ER_SLAVE_RELAY_LOG_WRITE_FAILURE),
3163 "failed to write a Rotate event"
3164 " to the relay log, SHOW SLAVE STATUS may be"
3165 " inaccurate");
3166
1/2
✓ Branch 0 taken 11666 times.
✗ Branch 1 not taken.
11666 mysql_mutex_lock(&mi->data_lock);
3167
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 11665 times.
11666 if (flush_master_info(mi, force_flush_mi_info, false, false,
3168
2/4
✓ Branch 0 taken 11666 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11666 times.
✗ Branch 3 not taken.
11666 mi->is_gtid_only_mode())) {
3169 1 error = 1;
3170
8/16
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
1 LogErr(ERROR_LEVEL, ER_RPL_SLAVE_CANT_FLUSH_MASTER_INFO_FILE);
3171 }
3172
1/2
✓ Branch 0 taken 11666 times.
✗ Branch 1 not taken.
11666 mysql_mutex_unlock(&mi->data_lock);
3173
1/2
✓ Branch 0 taken 11666 times.
✗ Branch 1 not taken.
11666 delete ev;
3174 } else {
3175 1 error = 1;
3176
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 mi->report(ERROR_LEVEL, ER_SLAVE_CREATE_EVENT_FAILURE,
3177 ER_THD(thd, ER_SLAVE_CREATE_EVENT_FAILURE),
3178 "Rotate_event (out of memory?),"
3179 " SHOW SLAVE STATUS may be inaccurate");
3180 }
3181
3182 11667 return error;
3183 11667 }
3184
3185 /*
3186 Builds a Rotate from the ignored events' info and writes it to relay log.
3187
3188 @param thd pointer to I/O Thread's Thd.
3189 @param mi point to I/O Thread metadata class.
3190
3191 @return 0 if everything went fine, 1 otherwise.
3192 */
3193 6910 static int write_ignored_events_info_to_relay_log(THD *thd, Master_info *mi) {
3194 6910 Relay_log_info *rli = mi->rli;
3195 6910 mysql_mutex_t *end_pos_lock = rli->relay_log.get_binlog_end_pos_lock();
3196 6910 int error = 0;
3197
1/2
✓ Branch 0 taken 6910 times.
✗ Branch 1 not taken.
6910 DBUG_TRACE;
3198
3199
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6910 times.
6910 assert(thd == mi->info_thd);
3200
1/2
✓ Branch 0 taken 6910 times.
✗ Branch 1 not taken.
6910 mysql_mutex_lock(rli->relay_log.get_log_lock());
3201
1/2
✓ Branch 0 taken 6910 times.
✗ Branch 1 not taken.
6910 mysql_mutex_lock(end_pos_lock);
3202
3203
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 6906 times.
6910 if (rli->ign_master_log_name_end[0]) {
3204
3/8
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 4 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
4 DBUG_PRINT("info", ("writing a Rotate event to track down ignored events"));
3205 /*
3206 If the ignored events' info still hold, they should have same info as
3207 the mi->get_master_log_[name|pos].
3208 */
3209
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 assert(strcmp(rli->ign_master_log_name_end, mi->get_master_log_name()) ==
3210 0);
3211
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 assert(rli->ign_master_log_pos_end == mi->get_master_log_pos());
3212
3213 /* Avoid the applier to get the ignored event' info by rli->ign* */
3214 4 rli->ign_master_log_name_end[0] = 0;
3215 /* can unlock before writing as the relay log will soon have our Rotate */
3216
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 mysql_mutex_unlock(end_pos_lock);
3217
3218 /* Generate the rotate based on mi position */
3219
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 error = write_rotate_to_master_pos_into_relay_log(
3220 thd, mi, false /* force_flush_mi_info */);
3221 } else
3222
1/2
✓ Branch 0 taken 6906 times.
✗ Branch 1 not taken.
6906 mysql_mutex_unlock(end_pos_lock);
3223
3224
1/2
✓ Branch 0 taken 6910 times.
✗ Branch 1 not taken.
6910 mysql_mutex_unlock(rli->relay_log.get_log_lock());
3225 6910 return error;
3226 6910 }
3227
3228 7117 static int register_slave_on_master(MYSQL *mysql, Master_info *mi,
3229 bool *suppress_warnings) {
3230 7117 uchar buf[1024], *pos = buf;
3231 7117 size_t report_host_len = 0, report_user_len = 0, report_password_len = 0;
3232
1/2
✓ Branch 0 taken 7118 times.
✗ Branch 1 not taken.
7117 DBUG_TRACE;
3233
3234 7118 *suppress_warnings = false;
3235
2/2
✓ Branch 0 taken 6566 times.
✓ Branch 1 taken 552 times.
7118 if (report_host) report_host_len = strlen(report_host);
3236
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7118 times.
7118 if (report_host_len > HOSTNAME_LENGTH) {
3237 LogErr(WARNING_LEVEL, ER_RPL_SLAVE_REPORT_HOST_TOO_LONG, report_host_len,
3238 HOSTNAME_LENGTH, mi->get_for_channel_str());
3239 return 0;
3240 }
3241
3242
2/2
✓ Branch 0 taken 6563 times.
✓ Branch 1 taken 555 times.
7118 if (report_user) report_user_len = strlen(report_user);
3243
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7118 times.
7118 if (report_user_len > USERNAME_LENGTH) {
3244 LogErr(WARNING_LEVEL, ER_RPL_SLAVE_REPORT_USER_TOO_LONG, report_user_len,
3245 USERNAME_LENGTH, mi->get_for_channel_str());
3246 return 0;
3247 }
3248
3249
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7111 times.
7118 if (report_password) report_password_len = strlen(report_password);
3250
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7118 times.
7118 if (report_password_len > MAX_PASSWORD_LENGTH) {
3251 LogErr(WARNING_LEVEL, ER_RPL_SLAVE_REPORT_PASSWORD_TOO_LONG,
3252 report_password_len, MAX_PASSWORD_LENGTH, mi->get_for_channel_str());
3253 return 0;
3254 }
3255
3256 7118 int4store(pos, server_id);
3257 7117 pos += 4;
3258
1/2
✓ Branch 0 taken 7117 times.
✗ Branch 1 not taken.
7117 pos = net_store_data(pos, (uchar *)report_host, report_host_len);
3259
1/2
✓ Branch 0 taken 7118 times.
✗ Branch 1 not taken.
7117 pos = net_store_data(pos, (uchar *)report_user, report_user_len);
3260
1/2
✓ Branch 0 taken 7118 times.
✗ Branch 1 not taken.
7118 pos = net_store_data(pos, (uchar *)report_password, report_password_len);
3261 7118 int2store(pos, (uint16)report_port);
3262 7118 pos += 2;
3263 /*
3264 Fake rpl_recovery_rank, which was removed in BUG#13963,
3265 so that this server can register itself on old servers,
3266 see BUG#49259.
3267 */
3268 7118 int4store(pos, /* rpl_recovery_rank */ 0);
3269 7118 pos += 4;
3270 /* The master will fill in master_id */
3271 7118 int4store(pos, 0);
3272 7118 pos += 4;
3273
3274
4/8
✓ Branch 0 taken 7118 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7118 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 84 times.
✓ Branch 7 taken 7034 times.
7118 if (simple_command(mysql, COM_REGISTER_SLAVE, buf, (size_t)(pos - buf), 0)) {
3275
1/2
✓ Branch 0 taken 84 times.
✗ Branch 1 not taken.
84 uint err{mysql_errno(mysql)};
3276
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 84 times.
84 if (err == ER_NET_READ_INTERRUPTED) {
3277 *suppress_warnings = true; // Suppress reconnect warning
3278
2/4
✓ Branch 0 taken 84 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 84 times.
✗ Branch 3 not taken.
84 } else if (!check_io_slave_killed(mi->info_thd, mi, nullptr)) {
3279
1/2
✓ Branch 0 taken 84 times.
✗ Branch 1 not taken.
84 std::stringstream ss;
3280
5/10
✓ Branch 0 taken 84 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 84 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 84 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 84 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 84 times.
✗ Branch 9 not taken.
84 ss << mysql_error(mysql) << " (Errno: " << err << ")";
3281
1/2
✓ Branch 0 taken 84 times.
✗ Branch 1 not taken.
168 mi->report(ERROR_LEVEL, ER_SLAVE_MASTER_COM_FAILURE,
3282
2/4
✓ Branch 0 taken 84 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 84 times.
✗ Branch 3 not taken.
84 ER_THD(current_thd, ER_SLAVE_MASTER_COM_FAILURE),
3283
1/2
✓ Branch 0 taken 84 times.
✗ Branch 1 not taken.
168 "COM_REGISTER_SLAVE", ss.str().c_str());
3284 84 }
3285
2/4
✓ Branch 0 taken 84 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 84 times.
84 if (is_network_error(err)) mi->set_network_error();
3286 84 return 1;
3287 }
3288
3289
3/4
✓ Branch 0 taken 7034 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 7033 times.
7034 DBUG_EXECUTE_IF("simulate_register_replica_killed", {
3290 mi->abort_slave = 1;
3291 return 1;
3292 };);
3293 7033 return 0;
3294 7118 }
3295
3296 /**
3297 Function that fills the metadata required for SHOW REPLICA STATUS.
3298 This function shall be used in two cases:
3299 1) SHOW REPLICA STATUS FOR ALL CHANNELS
3300 2) SHOW REPLICA STATUS for a channel
3301
3302 @param[in,out] field_list field_list to fill the metadata
3303 @param[in] io_gtid_set_size the size to be allocated to store
3304 the retrieved gtid set
3305 @param[in] sql_gtid_set_size the size to be allocated to store
3306 the executed gtid set
3307
3308 @todo return a bool after adding catching the exceptions to the
3309 push_back() methods for field_list.
3310 */
3311
3312 173123 static void show_slave_status_metadata(mem_root_deque<Item *> *field_list,
3313 int io_gtid_set_size,
3314 int sql_gtid_set_size) {
3315
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 field_list->push_back(new Item_empty_string("Replica_IO_State", 14));
3316 346246 field_list->push_back(
3317
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 new Item_empty_string("Source_Host", HOSTNAME_LENGTH + 1));
3318 346246 field_list->push_back(
3319
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 new Item_empty_string("Source_User", USERNAME_LENGTH + 1));
3320
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 field_list->push_back(new Item_return_int("Source_Port", 7, MYSQL_TYPE_LONG));
3321 346246 field_list->push_back(
3322
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 new Item_return_int("Connect_Retry", 10, MYSQL_TYPE_LONG));
3323
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 field_list->push_back(new Item_empty_string("Source_Log_File", FN_REFLEN));
3324 346246 field_list->push_back(
3325
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 new Item_return_int("Read_Source_Log_Pos", 10, MYSQL_TYPE_LONGLONG));
3326
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 field_list->push_back(new Item_empty_string("Relay_Log_File", FN_REFLEN));
3327 346246 field_list->push_back(
3328
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 new Item_return_int("Relay_Log_Pos", 10, MYSQL_TYPE_LONGLONG));
3329 346246 field_list->push_back(
3330
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 new Item_empty_string("Relay_Source_Log_File", FN_REFLEN));
3331
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 field_list->push_back(new Item_empty_string("Replica_IO_Running", 3));
3332
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 field_list->push_back(new Item_empty_string("Replica_SQL_Running", 3));
3333
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 field_list->push_back(new Item_empty_string("Replicate_Do_DB", 20));
3334
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 field_list->push_back(new Item_empty_string("Replicate_Ignore_DB", 20));
3335
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 field_list->push_back(new Item_empty_string("Replicate_Do_Table", 20));
3336
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 field_list->push_back(new Item_empty_string("Replicate_Ignore_Table", 23));
3337
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 field_list->push_back(new Item_empty_string("Replicate_Wild_Do_Table", 24));
3338 346246 field_list->push_back(
3339
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 new Item_empty_string("Replicate_Wild_Ignore_Table", 28));
3340
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 field_list->push_back(new Item_return_int("Last_Errno", 4, MYSQL_TYPE_LONG));
3341
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 field_list->push_back(new Item_empty_string("Last_Error", 20));
3342 346246 field_list->push_back(
3343
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 new Item_return_int("Skip_Counter", 10, MYSQL_TYPE_LONG));
3344 346246 field_list->push_back(
3345
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 new Item_return_int("Exec_Source_Log_Pos", 10, MYSQL_TYPE_LONGLONG));
3346 346246 field_list->push_back(
3347
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 new Item_return_int("Relay_Log_Space", 10, MYSQL_TYPE_LONGLONG));
3348
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 field_list->push_back(new Item_empty_string("Until_Condition", 6));
3349
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 field_list->push_back(new Item_empty_string("Until_Log_File", FN_REFLEN));
3350 346246 field_list->push_back(
3351
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 new Item_return_int("Until_Log_Pos", 10, MYSQL_TYPE_LONGLONG));
3352
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 field_list->push_back(new Item_empty_string("Source_SSL_Allowed", 7));
3353
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 field_list->push_back(new Item_empty_string("Source_SSL_CA_File", FN_REFLEN));
3354
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 field_list->push_back(new Item_empty_string("Source_SSL_CA_Path", FN_REFLEN));
3355
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 field_list->push_back(new Item_empty_string("Source_SSL_Cert", FN_REFLEN));
3356
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 field_list->push_back(new Item_empty_string("Source_SSL_Cipher", FN_REFLEN));
3357
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 field_list->push_back(new Item_empty_string("Source_SSL_Key", FN_REFLEN));
3358 346246 field_list->push_back(
3359
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 new Item_return_int("Seconds_Behind_Source", 10, MYSQL_TYPE_LONGLONG));
3360 346246 field_list->push_back(
3361
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 new Item_empty_string("Source_SSL_Verify_Server_Cert", 3));
3362 346246 field_list->push_back(
3363
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 new Item_return_int("Last_IO_Errno", 4, MYSQL_TYPE_LONG));
3364
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 field_list->push_back(new Item_empty_string("Last_IO_Error", 20));
3365 346246 field_list->push_back(
3366
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 new Item_return_int("Last_SQL_Errno", 4, MYSQL_TYPE_LONG));
3367
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 field_list->push_back(new Item_empty_string("Last_SQL_Error", 20));
3368 346246 field_list->push_back(
3369
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 new Item_empty_string("Replicate_Ignore_Server_Ids", FN_REFLEN));
3370 346246 field_list->push_back(
3371
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 new Item_return_int("Source_Server_Id", sizeof(ulong), MYSQL_TYPE_LONG));
3372
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 field_list->push_back(new Item_empty_string("Source_UUID", UUID_LENGTH));
3373 346246 field_list->push_back(
3374
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 new Item_empty_string("Source_Info_File", 2 * FN_REFLEN));
3375
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 field_list->push_back(new Item_return_int("SQL_Delay", 10, MYSQL_TYPE_LONG));
3376 346246 field_list->push_back(
3377
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 new Item_return_int("SQL_Remaining_Delay", 8, MYSQL_TYPE_LONG));
3378
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 field_list->push_back(new Item_empty_string("Replica_SQL_Running_State", 20));
3379 346246 field_list->push_back(
3380
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 new Item_return_int("Source_Retry_Count", 10, MYSQL_TYPE_LONGLONG));
3381 346246 field_list->push_back(
3382
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 new Item_empty_string("Source_Bind", HOSTNAME_LENGTH + 1));
3383
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 field_list->push_back(new Item_empty_string("Last_IO_Error_Timestamp", 20));
3384
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 field_list->push_back(new Item_empty_string("Last_SQL_Error_Timestamp", 20));
3385
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 field_list->push_back(new Item_empty_string("Source_SSL_Crl", FN_REFLEN));
3386
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 field_list->push_back(new Item_empty_string("Source_SSL_Crlpath", FN_REFLEN));
3387 346246 field_list->push_back(
3388
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 new Item_empty_string("Retrieved_Gtid_Set", io_gtid_set_size));
3389 346246 field_list->push_back(
3390
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 new Item_empty_string("Executed_Gtid_Set", sql_gtid_set_size));
3391 346246 field_list->push_back(
3392
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 new Item_return_int("Auto_Position", sizeof(ulong), MYSQL_TYPE_LONG));
3393
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 field_list->push_back(new Item_empty_string("Replicate_Rewrite_DB", 24));
3394 346246 field_list->push_back(
3395
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 new Item_empty_string("Channel_Name", CHANNEL_NAME_LENGTH));
3396
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 field_list->push_back(new Item_empty_string("Source_TLS_Version", FN_REFLEN));
3397 346246 field_list->push_back(
3398
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 new Item_empty_string("Source_public_key_path", FN_REFLEN));
3399
2/4
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
346246 field_list->push_back(new Item_return_int("Get_Source_public_key",
3400
1/2
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
346246 sizeof(ulong), MYSQL_TYPE_LONG));
3401 346246 field_list->push_back(
3402
3/6
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 173123 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173123 times.
✗ Branch 5 not taken.
173123 new Item_empty_string("Network_Namespace", NAME_LEN + 1));
3403 173123 }
3404
3405 /**
3406 Send the data to the client of a Master_info during show_slave_status()
3407 This function has to be called after calling show_slave_status_metadata().
3408 Just before sending the data, thd->get_protocol() is prepared to (re)send;
3409
3410 @param[in] thd client thread
3411 @param[in] mi the master info. In the case of multisource
3412 replication, this master info corresponds to a
3413 channel.
3414
3415 @param[in] io_gtid_set_buffer buffer related to Retrieved GTID set
3416 for each channel.
3417 @param[in] sql_gtid_set_buffer buffer related to Executed GTID set
3418 for each channel.
3419 @retval 0 success
3420 @retval 1 Error
3421 */
3422
3423 147899 static bool show_slave_status_send_data(THD *thd, Master_info *mi,
3424 char *io_gtid_set_buffer,
3425 char *sql_gtid_set_buffer) {
3426
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147899 DBUG_TRACE;
3427
3428 147900 Protocol *protocol = thd->get_protocol();
3429 147900 char *slave_sql_running_state = nullptr;
3430 147900 Rpl_filter *rpl_filter = mi->rli->rpl_filter;
3431
3432
3/8
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 147900 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 147900 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
147900 DBUG_PRINT("info", ("host is set: '%s'", mi->host));
3433
3434
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 protocol->start_row();
3435
3436 /*
3437 slave_running can be accessed without run_lock but not other
3438 non-volatile members like mi->info_thd or rli->info_thd, for
3439 them either info_thd_lock or run_lock hold is required.
3440 */
3441
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 mysql_mutex_lock(&mi->info_thd_lock);
3442
4/6
✓ Branch 0 taken 87804 times.
✓ Branch 1 taken 60096 times.
✓ Branch 2 taken 87804 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 147900 times.
✗ Branch 5 not taken.
147900 protocol->store(mi->info_thd ? mi->info_thd->proc_info_session(thd) : "",
3443 &my_charset_bin);
3444
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 mysql_mutex_unlock(&mi->info_thd_lock);
3445
3446
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 mysql_mutex_lock(&mi->rli->info_thd_lock);
3447 65849 slave_sql_running_state = const_cast<char *>(
3448
3/4
✓ Branch 0 taken 82051 times.
✓ Branch 1 taken 65849 times.
✓ Branch 2 taken 82051 times.
✗ Branch 3 not taken.
147900 mi->rli->info_thd ? mi->rli->info_thd->proc_info_session(thd) : "");
3449
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 mysql_mutex_unlock(&mi->rli->info_thd_lock);
3450
3451
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 mysql_mutex_lock(&mi->data_lock);
3452
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 mysql_mutex_lock(&mi->rli->data_lock);
3453
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 mysql_mutex_lock(&mi->err_lock);
3454
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 mysql_mutex_lock(&mi->rli->err_lock);
3455
3456
3/4
✓ Branch 0 taken 147899 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 147899 times.
✗ Branch 3 not taken.
147900 DEBUG_SYNC(thd, "wait_after_lock_active_mi_and_rli_data_lock_is_acquired");
3457
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 protocol->store(mi->host, &my_charset_bin);
3458
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 protocol->store(mi->get_user(), &my_charset_bin);
3459
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 protocol->store((uint32)mi->port);
3460
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 protocol->store((uint32)mi->connect_retry);
3461
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 protocol->store(mi->get_master_log_name_info(), &my_charset_bin);
3462
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 protocol->store((ulonglong)mi->get_master_log_pos_info());
3463 147900 protocol->store(mi->rli->get_group_relay_log_name() +
3464
2/4
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 147900 times.
✗ Branch 3 not taken.
147900 dirname_length(mi->rli->get_group_relay_log_name()),
3465 &my_charset_bin);
3466
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 protocol->store((ulonglong)mi->rli->get_group_relay_log_pos());
3467
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 protocol->store(mi->rli->get_group_master_log_name_info(), &my_charset_bin);
3468
3/4
✓ Branch 0 taken 62600 times.
✓ Branch 1 taken 85300 times.
✓ Branch 2 taken 147900 times.
✗ Branch 3 not taken.
210500 protocol->store(
3469 147900 mi->slave_running == MYSQL_SLAVE_RUN_CONNECT
3470 ? "Yes"
3471
2/2
✓ Branch 0 taken 2503 times.
✓ Branch 1 taken 60097 times.
62600 : (mi->slave_running == MYSQL_SLAVE_RUN_NOT_CONNECT ? "Connecting"
3472 : "No"),
3473 &my_charset_bin);
3474
3/4
✓ Branch 0 taken 82040 times.
✓ Branch 1 taken 65860 times.
✓ Branch 2 taken 147900 times.
✗ Branch 3 not taken.
147900 protocol->store(mi->rli->slave_running ? "Yes" : "No", &my_charset_bin);
3475
3476 /*
3477 Acquire the read lock, because the filter may be modified by
3478 CHANGE REPLICATION FILTER when slave is not running.
3479 */
3480
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 rpl_filter->rdlock();
3481
2/4
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 147900 times.
✗ Branch 3 not taken.
147900 store(protocol, rpl_filter->get_do_db());
3482
2/4
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 147900 times.
✗ Branch 3 not taken.
147900 store(protocol, rpl_filter->get_ignore_db());
3483
3484 char buf[256];
3485 147900 String tmp(buf, sizeof(buf), &my_charset_bin);
3486
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 rpl_filter->get_do_table(&tmp);
3487
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 protocol->store(&tmp);
3488
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 rpl_filter->get_ignore_table(&tmp);
3489
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 protocol->store(&tmp);
3490
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 rpl_filter->get_wild_do_table(&tmp);
3491
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 protocol->store(&tmp);
3492
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 rpl_filter->get_wild_ignore_table(&tmp);
3493
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 protocol->store(&tmp);
3494
3495
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 protocol->store(mi->rli->last_error().number);
3496
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 protocol->store(mi->rli->last_error().message, &my_charset_bin);
3497
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 protocol->store((uint32)mi->rli->slave_skip_counter);
3498
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 protocol->store((ulonglong)mi->rli->get_group_master_log_pos_info());
3499
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 protocol->store((ulonglong)mi->rli->log_space_total);
3500
3501 147900 const char *until_type = "";
3502
3503
8/9
✓ Branch 0 taken 147065 times.
✓ Branch 1 taken 370 times.
✓ Branch 2 taken 112 times.
✓ Branch 3 taken 218 times.
✓ Branch 4 taken 16 times.
✓ Branch 5 taken 19 times.
✓ Branch 6 taken 23 times.
✓ Branch 7 taken 77 times.
✗ Branch 8 not taken.
147900 switch (mi->rli->until_condition) {
3504 147065 case Relay_log_info::UNTIL_NONE:
3505 147065 until_type = "None";
3506 147065 break;
3507 370 case Relay_log_info::UNTIL_MASTER_POS:
3508
2/2
✓ Branch 0 taken 369 times.
✓ Branch 1 taken 1 times.
370 if (thd->lex->is_replication_deprecated_syntax_used())
3509 369 until_type = "Master";
3510 else
3511 1 until_type = "Source";
3512 370 break;
3513 112 case Relay_log_info::UNTIL_RELAY_POS:
3514 112 until_type = "Relay";
3515 112 break;
3516 218 case Relay_log_info::UNTIL_SQL_BEFORE_GTIDS:
3517 218 until_type = "SQL_BEFORE_GTIDS";
3518 218 break;
3519 16 case Relay_log_info::UNTIL_SQL_AFTER_GTIDS:
3520 16 until_type = "SQL_AFTER_GTIDS";
3521 16 break;
3522 19 case Relay_log_info::UNTIL_SQL_VIEW_ID:
3523 19 until_type = "SQL_VIEW_ID";
3524 19 break;
3525 23 case Relay_log_info::UNTIL_SQL_AFTER_MTS_GAPS:
3526 23 until_type = "SQL_AFTER_MTS_GAPS";
3527 23 break;
3528 77 case Relay_log_info::UNTIL_DONE:
3529 77 until_type = "DONE";
3530 77 break;
3531 default:
3532 assert(0);
3533 }
3534
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 protocol->store(until_type, &my_charset_bin);
3535
2/4
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 147900 times.
✗ Branch 3 not taken.
147900 protocol->store(mi->rli->get_until_log_name(), &my_charset_bin);
3536
2/4
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 147900 times.
✗ Branch 3 not taken.
147900 protocol->store((ulonglong)mi->rli->get_until_log_pos());
3537
3538
3/4
✓ Branch 0 taken 1882 times.
✓ Branch 1 taken 146018 times.
✓ Branch 2 taken 147900 times.
✗ Branch 3 not taken.
147900 protocol->store(mi->ssl ? "Yes" : "No", &my_charset_bin);
3539
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 protocol->store(mi->ssl_ca, &my_charset_bin);
3540
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 protocol->store(mi->ssl_capath, &my_charset_bin);
3541
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 protocol->store(mi->ssl_cert, &my_charset_bin);
3542
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 protocol->store(mi->ssl_cipher, &my_charset_bin);
3543
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 protocol->store(mi->ssl_key, &my_charset_bin);
3544
3545 /*
3546 The pseudo code to compute Seconds_Behind_Master:
3547 if (SQL thread is running)
3548 {
3549 if (SQL thread processed all the available relay log)
3550 {
3551 if (IO thread is running)
3552 print 0;
3553 else
3554 print NULL;
3555 }
3556 else
3557 compute Seconds_Behind_Master;
3558 }
3559 else
3560 print NULL;
3561 */
3562
3563
2/2
✓ Branch 0 taken 82040 times.
✓ Branch 1 taken 65860 times.
147900 if (mi->rli->slave_running) {
3564 /*
3565 Check if SQL thread is at the end of relay log
3566 Checking should be done using two conditions
3567 condition1: compare the log positions and
3568 condition2: compare the file names (to handle rotation case)
3569 */
3570
4/4
✓ Branch 0 taken 37272 times.
✓ Branch 1 taken 44768 times.
✓ Branch 2 taken 36989 times.
✓ Branch 3 taken 45051 times.
119312 if ((mi->get_master_log_pos() == mi->rli->get_group_master_log_pos()) &&
3571
2/2
✓ Branch 0 taken 36989 times.
✓ Branch 1 taken 283 times.
37272 (!strcmp(mi->get_master_log_name(),
3572 37272 mi->rli->get_group_master_log_name()))) {
3573
2/2
✓ Branch 0 taken 34831 times.
✓ Branch 1 taken 2158 times.
36989 if (mi->slave_running == MYSQL_SLAVE_RUN_CONNECT)
3574
1/2
✓ Branch 0 taken 34831 times.
✗ Branch 1 not taken.
34831 protocol->store(0LL);
3575 else
3576
1/2
✓ Branch 0 taken 2158 times.
✗ Branch 1 not taken.
2158 protocol->store_null();
3577 } else {
3578 45051 long time_diff = ((long)(time(nullptr) - mi->rli->last_master_timestamp) -
3579 45051 mi->clock_diff_with_master);
3580 /*
3581 Apparently on some systems time_diff can be <0. Here are possible
3582 reasons related to MySQL:
3583 - the master is itself a slave of another master whose time is ahead.
3584 - somebody used an explicit SET TIMESTAMP on the master.
3585 Possible reason related to granularity-to-second of time functions
3586 (nothing to do with MySQL), which can explain a value of -1:
3587 assume the master's and slave's time are perfectly synchronized, and
3588 that at slave's connection time, when the master's timestamp is read,
3589 it is at the very end of second 1, and (a very short time later) when
3590 the slave's timestamp is read it is at the very beginning of second
3591 2. Then the recorded value for master is 1 and the recorded value for
3592 slave is 2. At SHOW REPLICA STATUS time, assume that the difference
3593 between timestamp of slave and rli->last_master_timestamp is 0
3594 (i.e. they are in the same second), then we get 0-(2-1)=-1 as a result.
3595 This confuses users, so we don't go below 0: hence the max().
3596
3597 last_master_timestamp == 0 (an "impossible" timestamp 1970) is a
3598 special marker to say "consider we have caught up".
3599 */
3600
1/2
✓ Branch 0 taken 45051 times.
✗ Branch 1 not taken.
45051 protocol->store(
3601
2/2
✓ Branch 0 taken 37108 times.
✓ Branch 1 taken 7943 times.
90102 (longlong)(mi->rli->last_master_timestamp ? max(0L, time_diff) : 0));
3602 }
3603 } else {
3604
1/2
✓ Branch 0 taken 65860 times.
✗ Branch 1 not taken.
65860 protocol->store_null();
3605 }
3606
3/4
✓ Branch 0 taken 148 times.
✓ Branch 1 taken 147752 times.
✓ Branch 2 taken 147900 times.
✗ Branch 3 not taken.
147900 protocol->store(mi->ssl_verify_server_cert ? "Yes" : "No", &my_charset_bin);
3607
3608 // Last_IO_Errno
3609
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 protocol->store(mi->last_error().number);
3610 // Last_IO_Error
3611
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 protocol->store(mi->last_error().message, &my_charset_bin);
3612 // Last_SQL_Errno
3613
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 protocol->store(mi->rli->last_error().number);
3614 // Last_SQL_Error
3615
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 protocol->store(mi->rli->last_error().message, &my_charset_bin);
3616 // Replicate_Ignore_Server_Ids
3617 {
3618 char buff[FN_REFLEN];
3619 ulong i, cur_len;
3620 147900 for (i = 0, buff[0] = 0, cur_len = 0;
3621
3/4
✓ Branch 0 taken 148504 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 604 times.
✓ Branch 3 taken 147900 times.
148504 i < mi->ignore_server_ids->dynamic_ids.size(); i++) {
3622 ulong s_id, slen;
3623 char sbuff[FN_REFLEN];
3624
1/2
✓ Branch 0 taken 604 times.
✗ Branch 1 not taken.
604 s_id = mi->ignore_server_ids->dynamic_ids[i];
3625
2/2
✓ Branch 0 taken 206 times.
✓ Branch 1 taken 398 times.
604 slen = sprintf(sbuff, (i == 0 ? "%lu" : ", %lu"), s_id);
3626
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 604 times.
604 if (cur_len + slen + 4 > FN_REFLEN) {
3627 /*
3628 break the loop whenever remained space could not fit
3629 ellipses on the next cycle
3630 */
3631 sprintf(buff + cur_len, "...");
3632 break;
3633 }
3634 604 cur_len += sprintf(buff + cur_len, "%s", sbuff);
3635 }
3636
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 protocol->store(buff, &my_charset_bin);
3637 }
3638 // Master_Server_id
3639
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 protocol->store((uint32)mi->master_id);
3640
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 protocol->store(mi->master_uuid, &my_charset_bin);
3641 // Master_Info_File
3642
2/4
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 147900 times.
✗ Branch 3 not taken.
147900 protocol->store(mi->get_description_info(), &my_charset_bin);
3643 // SQL_Delay
3644
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 protocol->store((uint32)mi->rli->get_sql_delay());
3645 // SQL_Remaining_Delay
3646
2/2
✓ Branch 0 taken 371 times.
✓ Branch 1 taken 147529 times.
147900 if (slave_sql_running_state == stage_sql_thd_waiting_until_delay.m_name) {
3647 371 time_t t = time(nullptr), sql_delay_end = mi->rli->get_sql_delay_end();
3648
2/4
✓ Branch 0 taken 371 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 371 times.
✗ Branch 3 not taken.
371 protocol->store((uint32)(t < sql_delay_end ? sql_delay_end - t : 0));
3649 } else
3650
1/2
✓ Branch 0 taken 147529 times.
✗ Branch 1 not taken.
147529 protocol->store_null();
3651 // Slave_SQL_Running_State
3652
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 protocol->store(slave_sql_running_state, &my_charset_bin);
3653 // Master_Retry_Count
3654
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 protocol->store((ulonglong)mi->retry_count);
3655 // Master_Bind
3656
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 protocol->store(mi->bind_addr, &my_charset_bin);
3657 // Last_IO_Error_Timestamp
3658
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 protocol->store(mi->last_error().timestamp, &my_charset_bin);
3659 // Last_SQL_Error_Timestamp
3660
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 protocol->store(mi->rli->last_error().timestamp, &my_charset_bin);
3661 // Master_Ssl_Crl
3662
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 protocol->store(mi->ssl_crl, &my_charset_bin);
3663 // Master_Ssl_Crlpath
3664
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 protocol->store(mi->ssl_crlpath, &my_charset_bin);
3665 // Retrieved_Gtid_Set
3666
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 protocol->store(io_gtid_set_buffer, &my_charset_bin);
3667 // Executed_Gtid_Set
3668
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 protocol->store(sql_gtid_set_buffer, &my_charset_bin);
3669 // Auto_Position
3670
3/4
✓ Branch 0 taken 38827 times.
✓ Branch 1 taken 109073 times.
✓ Branch 2 taken 147900 times.
✗ Branch 3 not taken.
147900 protocol->store(mi->is_auto_position() ? 1 : 0);
3671 // Replicate_Rewrite_DB
3672
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 rpl_filter->get_rewrite_db(&tmp);
3673
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 protocol->store(&tmp);
3674 // channel_name
3675
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 protocol->store(mi->get_channel(), &my_charset_bin);
3676 // Master_TLS_Version
3677
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 protocol->store(mi->tls_version, &my_charset_bin);
3678 // Master_public_key_path
3679
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 protocol->store(mi->public_key_path, &my_charset_bin);
3680 // Get_master_public_key
3681
3/4
✓ Branch 0 taken 1346 times.
✓ Branch 1 taken 146554 times.
✓ Branch 2 taken 147900 times.
✗ Branch 3 not taken.
147900 protocol->store(mi->get_public_key ? 1 : 0);
3682
3683
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 protocol->store(mi->network_namespace_str(), &my_charset_bin);
3684
3685
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 rpl_filter->unlock();
3686
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 mysql_mutex_unlock(&mi->rli->err_lock);
3687
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 mysql_mutex_unlock(&mi->err_lock);
3688
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 mysql_mutex_unlock(&mi->rli->data_lock);
3689
1/2
✓ Branch 0 taken 147900 times.
✗ Branch 1 not taken.
147900 mysql_mutex_unlock(&mi->data_lock);
3690
3691 147900 return false;
3692 147900 }
3693
3694 /**
3695 Method to the show the replication status in all channels.
3696
3697 @param[in] thd the client thread
3698
3699 @retval 0 success
3700 @retval 1 Error
3701
3702 */
3703 168971 bool show_slave_status(THD *thd) {
3704 168971 Protocol *protocol = thd->get_protocol();
3705 168973 int sql_gtid_set_size = 0, io_gtid_set_size = 0;
3706 168973 Master_info *mi = nullptr;
3707 168973 char *sql_gtid_set_buffer = nullptr;
3708 char **io_gtid_set_buffer_array;
3709 /*
3710 We need the maximum size of the retrieved gtid set (i.e io_gtid_set_size).
3711 This size is needed to reserve the place in show_slave_status_metadata().
3712 So, we travel all the mi's and find out the maximum size of io_gtid_set_size
3713 and pass it through show_slave_status_metadata()
3714 */
3715 168973 int max_io_gtid_set_size = io_gtid_set_size;
3716 uint idx;
3717 uint num_io_gtid_sets;
3718 168973 bool ret = true;
3719
3720
1/2
✓ Branch 0 taken 168974 times.
✗ Branch 1 not taken.
168973 DBUG_TRACE;
3721
3722
1/2
✓ Branch 0 taken 168973 times.
✗ Branch 1 not taken.
168974 channel_map.assert_some_lock();
3723
3724
1/2
✓ Branch 0 taken 168973 times.
✗ Branch 1 not taken.
168973 num_io_gtid_sets = channel_map.get_num_instances();
3725
3726 io_gtid_set_buffer_array =
3727 337946 (char **)my_malloc(key_memory_show_replica_status_io_gtid_set,
3728
1/2
✓ Branch 0 taken 168973 times.
✗ Branch 1 not taken.
168973 num_io_gtid_sets * sizeof(char *), MYF(MY_WME));
3729
3730
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 168973 times.
168973 if (io_gtid_set_buffer_array == nullptr) return true;
3731
3732
1/2
✓ Branch 0 taken 168974 times.
✗ Branch 1 not taken.
168973 global_sid_lock->wrlock();
3733
3734 168974 const Gtid_set *sql_gtid_set = gtid_state->get_executed_gtids();
3735
1/2
✓ Branch 0 taken 168974 times.
✗ Branch 1 not taken.
168974 sql_gtid_set_size = sql_gtid_set->to_string(&sql_gtid_set_buffer);
3736
3737
1/2
✓ Branch 0 taken 168974 times.
✗ Branch 1 not taken.
168974 global_sid_lock->unlock();
3738
3739 168974 idx = 0;
3740
4/6
✓ Branch 0 taken 168974 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 342248 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173274 times.
✓ Branch 5 taken 168974 times.
342248 for (mi_map::iterator it = channel_map.begin(); it != channel_map.end();
3741 173274 it++) {
3742 173274 mi = it->second;
3743 /*
3744 The following statement is needed because, when mi->host[0]=0
3745 we don't alloc memory for retried_gtid_set. However, we try
3746 to free it at the end, causing a crash. To be on safeside,
3747 we initialize it to NULL, so that my_free() takes care of it.
3748 */
3749 173274 io_gtid_set_buffer_array[idx] = nullptr;
3750
3751
2/2
✓ Branch 0 taken 143760 times.
✓ Branch 1 taken 29514 times.
173274 if (Master_info::is_configured(mi)) {
3752 143760 const Gtid_set *io_gtid_set = mi->rli->get_gtid_set();
3753
1/2
✓ Branch 0 taken 143760 times.
✗ Branch 1 not taken.
143760 mi->rli->get_sid_lock()->wrlock();
3754
3755 /*
3756 @todo: a single memory allocation improves speed,
3757 instead of doing it for each loop
3758 */
3759
3760 143760 if ((io_gtid_set_size =
3761
2/4
✓ Branch 0 taken 143760 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 143760 times.
143760 io_gtid_set->to_string(&io_gtid_set_buffer_array[idx])) < 0) {
3762 my_eof(thd);
3763 my_free(sql_gtid_set_buffer);
3764
3765 for (uint i = 0; i < idx - 1; i++) {
3766 my_free(io_gtid_set_buffer_array[i]);
3767 }
3768 my_free(io_gtid_set_buffer_array);
3769
3770 mi->rli->get_sid_lock()->unlock();
3771 return true;
3772 } else
3773 143760 max_io_gtid_set_size = max_io_gtid_set_size > io_gtid_set_size
3774
2/2
✓ Branch 0 taken 140 times.
✓ Branch 1 taken 143620 times.
143760 ? max_io_gtid_set_size
3775 : io_gtid_set_size;
3776
3777
1/2
✓ Branch 0 taken 143760 times.
✗ Branch 1 not taken.
143760 mi->rli->get_sid_lock()->unlock();
3778 }
3779 173274 idx++;
3780 }
3781
3782 168974 mem_root_deque<Item *> field_list(thd->mem_root);
3783
1/2
✓ Branch 0 taken 168974 times.
✗ Branch 1 not taken.
168974 show_slave_status_metadata(&field_list, max_io_gtid_set_size,
3784 sql_gtid_set_size);
3785
3786 // TODO: once the old syntax is removed, remove this as well.
3787
2/2
✓ Branch 0 taken 140179 times.
✓ Branch 1 taken 28795 times.
168974 if (thd->lex->is_replication_deprecated_syntax_used())
3788
1/2
✓ Branch 0 taken 140179 times.
✗ Branch 1 not taken.
140179 rename_fields_use_old_replica_source_terms(thd, field_list);
3789
3790
2/4
✓ Branch 0 taken 168974 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 168974 times.
168974 if (thd->send_result_metadata(field_list,
3791 Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) {
3792 goto err;
3793 }
3794
3795 /* Run through each mi */
3796
3797 168974 idx = 0;
3798
4/6
✓ Branch 0 taken 168973 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 342248 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 173274 times.
✓ Branch 5 taken 168974 times.
342248 for (mi_map::iterator it = channel_map.begin(); it != channel_map.end();
3799 173273 it++) {
3800 173274 mi = it->second;
3801
3802
2/2
✓ Branch 0 taken 143759 times.
✓ Branch 1 taken 29513 times.
173274 if (Master_info::is_configured(mi)) {
3803
2/4
✓ Branch 0 taken 143760 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 143760 times.
143759 if (show_slave_status_send_data(thd, mi, io_gtid_set_buffer_array[idx],
3804 sql_gtid_set_buffer))
3805 goto err;
3806
3807
2/4
✓ Branch 0 taken 143760 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 143760 times.
143760 if (protocol->end_row()) goto err;
3808 }
3809 173273 idx++;
3810 }
3811
3812 168974 ret = false;
3813 168974 err:
3814
1/2
✓ Branch 0 taken 168974 times.
✗ Branch 1 not taken.
168974 my_eof(thd);
3815
2/2
✓ Branch 0 taken 173274 times.
✓ Branch 1 taken 168974 times.
342248 for (uint i = 0; i < num_io_gtid_sets; i++) {
3816
1/2
✓ Branch 0 taken 173274 times.
✗ Branch 1 not taken.
173274 my_free(io_gtid_set_buffer_array[i]);
3817 }
3818
1/2
✓ Branch 0 taken 168974 times.
✗ Branch 1 not taken.
168974 my_free(io_gtid_set_buffer_array);
3819
1/2
✓ Branch 0 taken 168974 times.
✗ Branch 1 not taken.
168974 my_free(sql_gtid_set_buffer);
3820
3821 168974 return ret;
3822 168974 }
3823
3824 /**
3825 Execute a SHOW REPLICA STATUS statement.
3826
3827 @param thd Pointer to THD object for the client thread executing the
3828 statement.
3829
3830 @param mi Pointer to Master_info object for the IO thread.
3831
3832 @retval false success
3833 @retval true failure
3834
3835 Currently, show slave status works for a channel too, in multisource
3836 replication. But using performance schema tables is better.
3837
3838 */
3839 4149 bool show_slave_status(THD *thd, Master_info *mi) {
3840 4149 Protocol *protocol = thd->get_protocol();
3841 4149 char *sql_gtid_set_buffer = nullptr, *io_gtid_set_buffer = nullptr;
3842 4149 int sql_gtid_set_size = 0, io_gtid_set_size = 0;
3843
1/2
✓ Branch 0 taken 4149 times.
✗ Branch 1 not taken.
4149 DBUG_TRACE;
3844
3845
1/2
✓ Branch 0 taken 4149 times.
✗ Branch 1 not taken.
4149 if (mi != nullptr) {
3846
1/2
✓ Branch 0 taken 4149 times.
✗ Branch 1 not taken.
4149 global_sid_lock->wrlock();
3847 4149 const Gtid_set *sql_gtid_set = gtid_state->get_executed_gtids();
3848
1/2
✓ Branch 0 taken 4149 times.
✗ Branch 1 not taken.
4149 sql_gtid_set_size = sql_gtid_set->to_string(&sql_gtid_set_buffer);
3849
1/2
✓ Branch 0 taken 4149 times.
✗ Branch 1 not taken.
4149 global_sid_lock->unlock();
3850
3851
1/2
✓ Branch 0 taken 4149 times.
✗ Branch 1 not taken.
4149 mi->rli->get_sid_lock()->wrlock();
3852 4149 const Gtid_set *io_gtid_set = mi->rli->get_gtid_set();
3853
1/2
✓ Branch 0 taken 4149 times.
✗ Branch 1 not taken.
4149 io_gtid_set_size = io_gtid_set->to_string(&io_gtid_set_buffer);
3854
1/2
✓ Branch 0 taken 4149 times.
✗ Branch 1 not taken.
4149 mi->rli->get_sid_lock()->unlock();
3855
3856
2/4
✓ Branch 0 taken 4149 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4149 times.
4149 if (sql_gtid_set_size < 0 || io_gtid_set_size < 0) {
3857 my_eof(thd);
3858 my_free(sql_gtid_set_buffer);
3859 my_free(io_gtid_set_buffer);
3860 return true;
3861 }
3862 }
3863
3864 /* Fill the metadata required for show slave status. */
3865
3866 4149 mem_root_deque<Item *> field_list(thd->mem_root);
3867
1/2
✓ Branch 0 taken 4149 times.
✗ Branch 1 not taken.
4149 show_slave_status_metadata(&field_list, io_gtid_set_size, sql_gtid_set_size);
3868
3869 // TODO: once the old syntax is removed, remove this as well.
3870
2/2
✓ Branch 0 taken 4095 times.
✓ Branch 1 taken 54 times.
4149 if (thd->lex->is_replication_deprecated_syntax_used())
3871
1/2
✓ Branch 0 taken 4095 times.
✗ Branch 1 not taken.
4095 rename_fields_use_old_replica_source_terms(thd, field_list);
3872
3873
2/4
✓ Branch 0 taken 4149 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4149 times.
4149 if (thd->send_result_metadata(field_list,
3874 Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) {
3875 my_free(sql_gtid_set_buffer);
3876 my_free(io_gtid_set_buffer);
3877 return true;
3878 }
3879
3880
2/2
✓ Branch 0 taken 4140 times.
✓ Branch 1 taken 9 times.
4149 if (Master_info::is_configured(mi)) {
3881
2/4
✓ Branch 0 taken 4140 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4140 times.
4140 if (show_slave_status_send_data(thd, mi, io_gtid_set_buffer,
3882 sql_gtid_set_buffer))
3883 return true;
3884
3885
2/4
✓ Branch 0 taken 4140 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4140 times.
4140 if (protocol->end_row()) {
3886 my_free(sql_gtid_set_buffer);
3887 my_free(io_gtid_set_buffer);
3888 return true;
3889 }
3890 }
3891
1/2
✓ Branch 0 taken 4149 times.
✗ Branch 1 not taken.
4149 my_eof(thd);
3892
1/2
✓ Branch 0 taken 4149 times.
✗ Branch 1 not taken.
4149 my_free(sql_gtid_set_buffer);
3893
1/2
✓ Branch 0 taken 4149 times.
✗ Branch 1 not taken.
4149 my_free(io_gtid_set_buffer);
3894 4149 return false;
3895 4149 }
3896
3897 /**
3898 Entry point for SHOW REPLICA STATUS command. Function displays
3899 the slave status for all channels or for a single channel
3900 based on the FOR CHANNEL clause.
3901
3902 @param[in] thd the client thread.
3903
3904 @retval false ok
3905 @retval true not ok
3906 */
3907 173130 bool show_slave_status_cmd(THD *thd) {
3908 173130 Master_info *mi = nullptr;
3909 173130 LEX *lex = thd->lex;
3910 bool res;
3911
3912
1/2
✓ Branch 0 taken 173132 times.
✗ Branch 1 not taken.
173130 DBUG_TRACE;
3913
3914
1/2
✓ Branch 0 taken 173132 times.
✗ Branch 1 not taken.
173132 channel_map.rdlock();
3915
3916
3/4
✓ Branch 0 taken 168974 times.
✓ Branch 1 taken 4158 times.
✓ Branch 2 taken 168974 times.
✗ Branch 3 not taken.
173132 if (!lex->mi.for_channel) res = show_slave_status(thd);
3917 #ifdef WITH_WSREP
3918 // Disable the SHOW SLAVE STATUS command with the wsrep channel
3919
6/8
✓ Branch 0 taken 4158 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4158 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 4156 times.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 4156 times.
4158 else if (lex->mi.channel && wsrep_is_wsrep_channel_name(lex->mi.channel)) {
3920
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_error(ER_SLAVE_CHANNEL_OPERATION_NOT_ALLOWED, MYF(0),
3921 "SHOW SLAVE STATUS", lex->mi.channel);
3922
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 channel_map.unlock();
3923 2 return true;
3924 }
3925 #endif
3926 else {
3927
1/2
✓ Branch 0 taken 4156 times.
✗ Branch 1 not taken.
4156 mi = channel_map.get_mi(lex->mi.channel);
3928
3929 /*
3930 When mi is NULL, that means the channel doesn't exist, SSS
3931 will throw an error.
3932 */
3933
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 4151 times.
4156 if (mi == nullptr) {
3934
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 my_error(ER_SLAVE_CHANNEL_DOES_NOT_EXIST, MYF(0), lex->mi.channel);
3935
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 channel_map.unlock();
3936 5 return true;
3937 }
3938
3939 /*
3940 If the channel being used is a group replication applier channel we
3941 need to disable the SHOW REPLICA STATUS command as its output is not
3942 compatible with this command.
3943 */
3944
3/4
✓ Branch 0 taken 4151 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 4149 times.
4151 if (channel_map.is_group_replication_channel_name(mi->get_channel(),
3945 true)) {
3946
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_error(ER_SLAVE_CHANNEL_OPERATION_NOT_ALLOWED, MYF(0),
3947 "SHOW SLAVE STATUS", mi->get_channel());
3948
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 channel_map.unlock();
3949 2 return true;
3950 }
3951
3952
1/2
✓ Branch 0 taken 4149 times.
✗ Branch 1 not taken.
4149 res = show_slave_status(thd, mi);
3953 }
3954
3955
1/2
✓ Branch 0 taken 173123 times.
✗ Branch 1 not taken.
173123 channel_map.unlock();
3956
3957 173123 return res;
3958 173132 }
3959
3960 88783 void set_slave_thread_options(THD *thd) {
3961
1/2
✓ Branch 0 taken 88818 times.
✗ Branch 1 not taken.
88783 DBUG_TRACE;
3962 /*
3963 It's nonsense to constrain the slave threads with max_join_size; if a
3964 query succeeded on master, we HAVE to execute it. So set
3965 OPTION_BIG_SELECTS. Setting max_join_size to HA_POS_ERROR is not enough
3966 (and it's not needed if we have OPTION_BIG_SELECTS) because an INSERT
3967 SELECT examining more than 4 billion rows would still fail (yes, because
3968 when max_join_size is 4G, OPTION_BIG_SELECTS is automatically set, but
3969 only for client threads.
3970 */
3971 88818 ulonglong options = thd->variables.option_bits | OPTION_BIG_SELECTS;
3972
2/2
✓ Branch 0 taken 85978 times.
✓ Branch 1 taken 2840 times.
88818 if (opt_log_replica_updates)
3973 85978 options |= OPTION_BIN_LOG;
3974 else
3975 2840 options &= ~OPTION_BIN_LOG;
3976 88818 thd->variables.option_bits = options;
3977 88818 thd->variables.completion_type = 0;
3978
3979 /* Do not track GTIDs for slave threads to avoid performance issues. */
3980 88818 thd->variables.session_track_gtids = SESSION_TRACK_GTIDS_OFF;
3981 88818 thd->rpl_thd_ctx.session_gtids_ctx()
3982
1/2
✓ Branch 0 taken 88815 times.
✗ Branch 1 not taken.
88817 .update_tracking_activeness_from_session_variable(thd);
3983
3984 /*
3985 Set autocommit= 1 when info tables are used and autocommit == 0 to
3986 avoid trigger asserts on mysql_execute_command(THD *thd) caused by
3987 info tables updates which do not commit, like Rotate, Stop and
3988 skipped events handling.
3989 */
3990
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 88815 times.
88815 if ((thd->variables.option_bits & OPTION_NOT_AUTOCOMMIT) &&
3991 (opt_mi_repository_id == INFO_REPOSITORY_TABLE ||
3992 opt_rli_repository_id == INFO_REPOSITORY_TABLE)) {
3993 thd->variables.option_bits |= OPTION_AUTOCOMMIT;
3994 thd->variables.option_bits &= ~OPTION_NOT_AUTOCOMMIT;
3995 thd->server_status |= SERVER_STATUS_AUTOCOMMIT;
3996 }
3997
3998 /*
3999 Set thread InnoDB high priority.
4000 */
4001
6/8
✓ Branch 0 taken 88816 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 88806 times.
✓ Branch 4 taken 8 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 8 times.
✗ Branch 7 not taken.
88815 DBUG_EXECUTE_IF("dbug_set_high_prio_sql_thread", {
4002 if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL ||
4003 thd->system_thread == SYSTEM_THREAD_SLAVE_WORKER)
4004 thd->thd_tx_priority = 1;
4005 });
4006 88816 }
4007
4008 30768 void set_slave_thread_default_charset(THD *thd, Relay_log_info const *rli) {
4009
1/2
✓ Branch 0 taken 30768 times.
✗ Branch 1 not taken.
30768 DBUG_TRACE;
4010
4011 30768 thd->variables.character_set_client =
4012 30768 global_system_variables.character_set_client;
4013 30768 thd->variables.collation_connection =
4014 30768 global_system_variables.collation_connection;
4015 30768 thd->variables.collation_server = global_system_variables.collation_server;
4016
1/2
✓ Branch 0 taken 30768 times.
✗ Branch 1 not taken.
30768 thd->update_charset();
4017
4018 /*
4019 We use a const cast here since the conceptual (and externally
4020 visible) behavior of the function is to set the default charset of
4021 the thread. That the cache has to be invalidated is a secondary
4022 effect.
4023 */
4024
1/2
✓ Branch 0 taken 30768 times.
✗ Branch 1 not taken.
30768 const_cast<Relay_log_info *>(rli)->cached_charset_invalidate();
4025 30768 }
4026
4027 /*
4028 init_replica_thread()
4029 */
4030
4031 56951 int init_replica_thread(THD *thd, SLAVE_THD_TYPE thd_type) {
4032
1/2
✓ Branch 0 taken 56951 times.
✗ Branch 1 not taken.
56951 DBUG_TRACE;
4033 #if !defined(NDEBUG)
4034 56951 int simulate_error = 0;
4035 #endif
4036 56951 thd->system_thread = (thd_type == SLAVE_THD_WORKER)
4037
2/2
✓ Branch 0 taken 17188 times.
✓ Branch 1 taken 39763 times.
74139 ? SYSTEM_THREAD_SLAVE_WORKER
4038 : (thd_type == SLAVE_THD_SQL)
4039
2/2
✓ Branch 0 taken 10056 times.
✓ Branch 1 taken 7132 times.
17188 ? SYSTEM_THREAD_SLAVE_SQL
4040 : SYSTEM_THREAD_SLAVE_IO;
4041
2/4
✓ Branch 0 taken 56951 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 56951 times.
✗ Branch 3 not taken.
56951 thd->get_protocol_classic()->init_net(nullptr);
4042 56951 thd->slave_thread = true;
4043 56951 thd->enable_slow_log = opt_log_slow_replica_statements;
4044
1/2
✓ Branch 0 taken 56951 times.
✗ Branch 1 not taken.
56951 set_slave_thread_options(thd);
4045
4046 /*
4047 Replication threads are:
4048 - background threads in the server, not user sessions,
4049 - yet still assigned a PROCESSLIST_ID,
4050 for historical reasons (displayed in SHOW PROCESSLIST).
4051 */
4052
1/2
✓ Branch 0 taken 56951 times.
✗ Branch 1 not taken.
56951 thd->set_new_thread_id();
4053
4054 #ifdef HAVE_PSI_THREAD_INTERFACE
4055 /*
4056 Populate the PROCESSLIST_ID in the instrumentation.
4057 */
4058
1/2
✓ Branch 0 taken 56951 times.
✗ Branch 1 not taken.
56951 struct PSI_thread *psi = PSI_THREAD_CALL(get_thread)();
4059
1/2
✓ Branch 0 taken 56951 times.
✗ Branch 1 not taken.
56951 PSI_THREAD_CALL(set_thread_id)(psi, thd->thread_id());
4060 #endif /* HAVE_PSI_THREAD_INTERFACE */
4061
4062
3/4
✓ Branch 0 taken 56951 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 56939 times.
56951 DBUG_EXECUTE_IF("simulate_io_replica_error_on_init",
4063 simulate_error |= (1 << SLAVE_THD_IO););
4064
3/4
✓ Branch 0 taken 56951 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 56939 times.
56951 DBUG_EXECUTE_IF("simulate_sql_replica_error_on_init",
4065 simulate_error |= (1 << SLAVE_THD_SQL););
4066
1/2
✓ Branch 0 taken 56951 times.
✗ Branch 1 not taken.
56951 thd->store_globals();
4067 #if !defined(NDEBUG)
4068
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 56939 times.
56951 if (simulate_error & (1 << thd_type)) {
4069 12 return -1;
4070 }
4071 #endif
4072
4073
2/2
✓ Branch 0 taken 10050 times.
✓ Branch 1 taken 46889 times.
56939 if (thd_type == SLAVE_THD_SQL) {
4074
1/2
✓ Branch 0 taken 10050 times.
✗ Branch 1 not taken.
10050 THD_STAGE_INFO(thd, stage_waiting_for_the_next_event_in_relay_log);
4075
1/2
✓ Branch 0 taken 10050 times.
✗ Branch 1 not taken.
10050 thd->set_command(
4076 COM_QUERY); // the SQL thread does not use the server protocol
4077 } else {
4078
1/2
✓ Branch 0 taken 46889 times.
✗ Branch 1 not taken.
46889 THD_STAGE_INFO(thd, stage_waiting_for_source_update);
4079 }
4080
1/2
✓ Branch 0 taken 56939 times.
✗ Branch 1 not taken.
56939 thd->set_time();
4081 /* Do not use user-supplied timeout value for system threads. */
4082 56939 thd->variables.lock_wait_timeout = LONG_TIMEOUT;
4083 56939 return 0;
4084 56951 }
4085
4086 /**
4087 Sleep for a given amount of time or until killed.
4088
4089 @param thd Thread context of the current thread.
4090 @param seconds The number of seconds to sleep.
4091 @param func Function object to check if the thread has been killed.
4092 @param info The Rpl_info object associated with this sleep.
4093
4094 @retval True if the thread has been killed, false otherwise.
4095 */
4096 template <typename killed_func, typename rpl_info>
4097 1484 static inline bool slave_sleep(THD *thd, time_t seconds, killed_func func,
4098 rpl_info info) {
4099 bool ret;
4100 struct timespec abstime;
4101 1484 mysql_mutex_t *lock = &info->sleep_lock;
4102 1484 mysql_cond_t *cond = &info->sleep_cond;
4103
4104 /* Absolute system time at which the sleep time expires. */
4105
1/2
✓ Branch 0 taken 742 times.
✗ Branch 1 not taken.
1484 set_timespec(&abstime, seconds);
4106
4107
1/2
✓ Branch 0 taken 742 times.
✗ Branch 1 not taken.
1484 mysql_mutex_lock(lock);
4108
1/2
✓ Branch 0 taken 742 times.
✗ Branch 1 not taken.
1484 thd->ENTER_COND(cond, lock, nullptr, nullptr);
4109
4110
3/4
✓ Branch 0 taken 772 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 742 times.
✓ Branch 3 taken 30 times.
1544 while (!(ret = func(thd, info))) {
4111
1/2
✓ Branch 0 taken 742 times.
✗ Branch 1 not taken.
1484 int error = mysql_cond_timedwait(cond, lock, &abstime);
4112
2/2
✓ Branch 0 taken 712 times.
✓ Branch 1 taken 30 times.
1484 if (is_timeout(error)) break;
4113 }
4114
4115
1/2
✓ Branch 0 taken 742 times.
✗ Branch 1 not taken.
1484 mysql_mutex_unlock(lock);
4116
1/2
✓ Branch 0 taken 742 times.
✗ Branch 1 not taken.
1484 thd->EXIT_COND(nullptr);
4117
4118 1484 return ret;
4119 }
4120
4121 /**
4122 Callback function for mysql_binlog_open().
4123
4124 Sets gtid data in the command packet.
4125
4126 @param rpl Replication stream information.
4127 @param packet_gtid_set Pointer to command packet where gtid
4128 data should be stored.
4129 */
4130 2245 static void fix_gtid_set(MYSQL_RPL *rpl, uchar *packet_gtid_set) {
4131 2245 Gtid_set *gtid_set = (Gtid_set *)rpl->gtid_set_arg;
4132
4133 2245 gtid_set->encode(packet_gtid_set);
4134 2245 }
4135
4136 7033 static int request_dump(THD *thd, MYSQL *mysql, MYSQL_RPL *rpl, Master_info *mi,
4137 bool *suppress_warnings) {
4138
1/2
✓ Branch 0 taken 7033 times.
✗ Branch 1 not taken.
7033 DBUG_TRACE;
4139 enum_server_command command =
4140
2/2
✓ Branch 0 taken 2245 times.
✓ Branch 1 taken 4788 times.
7033 mi->is_auto_position() ? COM_BINLOG_DUMP_GTID : COM_BINLOG_DUMP;
4141 /*
4142 Note: binlog_flags is always 0. However, in versions up to 5.6
4143 RC, the master would check the lowest bit and do something
4144 unexpected if it was set; in early versions of 5.6 it would also
4145 use the two next bits. Therefore, for backward compatibility,
4146 if we ever start to use the flags, we should leave the three
4147 lowest bits unused.
4148 */
4149 7033 uint binlog_flags = 0;
4150 7033 binlog_flags |= USE_HEARTBEAT_EVENT_V2;
4151
4152 7033 *suppress_warnings = false;
4153
5/8
✓ Branch 0 taken 7033 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5421 times.
✓ Branch 3 taken 1612 times.
✓ Branch 4 taken 1612 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 7033 times.
7033 if (RUN_HOOK(binlog_relay_io, before_request_transmit,
4154 (thd, mi, binlog_flags)))
4155 return 1;
4156
4157 7033 rpl->server_id = server_id;
4158 7033 rpl->flags = binlog_flags;
4159
4160
1/2
✓ Branch 0 taken 7033 times.
✗ Branch 1 not taken.
7033 Sid_map sid_map(nullptr); /* No lock needed */
4161 /*
4162 Note: should be declared at the same level as the mysql_binlog_open() call,
4163 as the latter might call fix_gtid_set() which in turns calls
4164 gtid_executed->encode().
4165 */
4166
1/2
✓ Branch 0 taken 7033 times.
✗ Branch 1 not taken.
7033 Gtid_set gtid_executed(&sid_map);
4167
4168
2/2
✓ Branch 0 taken 2245 times.
✓ Branch 1 taken 4788 times.
7033 if (command == COM_BINLOG_DUMP_GTID) {
4169 // get set of GTIDs
4170
1/2
✓ Branch 0 taken 2245 times.
✗ Branch 1 not taken.
2245 mi->rli->get_sid_lock()->wrlock();
4171
4172
2/4
✓ Branch 0 taken 2245 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2245 times.
2245 if (gtid_executed.add_gtid_set(mi->rli->get_gtid_set()) !=
4173 RETURN_STATUS_OK) {
4174 mi->rli->get_sid_lock()->unlock();
4175 return 1;
4176 }
4177
1/2
✓ Branch 0 taken 2245 times.
✗ Branch 1 not taken.
2245 mi->rli->get_sid_lock()->unlock();
4178
4179
1/2
✓ Branch 0 taken 2245 times.
✗ Branch 1 not taken.
2245 global_sid_lock->wrlock();
4180
1/2
✓ Branch 0 taken 2245 times.
✗ Branch 1 not taken.
2245 gtid_state->dbug_print();
4181
4182
2/4
✓ Branch 0 taken 2245 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2245 times.
2245 if (gtid_executed.add_gtid_set(gtid_state->get_executed_gtids()) !=
4183 RETURN_STATUS_OK) {
4184 global_sid_lock->unlock();
4185 return 1;
4186 }
4187
1/2
✓ Branch 0 taken 2245 times.
✗ Branch 1 not taken.
2245 global_sid_lock->unlock();
4188
4189 2245 rpl->file_name = nullptr; /* No need to set rpl.file_name_length */
4190 2245 rpl->start_position = 4;
4191 2245 rpl->flags |= MYSQL_RPL_GTID;
4192
1/2
✓ Branch 0 taken 2245 times.
✗ Branch 1 not taken.
2245 rpl->gtid_set_encoded_size = gtid_executed.get_encoded_length();
4193 2245 rpl->fix_gtid_set = fix_gtid_set;
4194 2245 rpl->gtid_set_arg = (void *)&gtid_executed;
4195 } else {
4196 4788 rpl->file_name_length = 0;
4197 4788 rpl->file_name = mi->get_master_log_name();
4198
2/4
✓ Branch 0 taken 4788 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4788 times.
✗ Branch 3 not taken.
4788 rpl->start_position = DBUG_EVALUATE_IF("request_source_log_pos_3", 3,
4199 mi->get_master_log_pos());
4200 }
4201
2/4
✓ Branch 0 taken 7033 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7033 times.
7033 if (mysql_binlog_open(mysql, rpl)) {
4202 /*
4203 Something went wrong, so we will just reconnect and retry later
4204 in the future, we should do a better error analysis, but for
4205 now we just fill up the error log :-)
4206 */
4207 uint err{mysql_errno(mysql)};
4208 if (err == ER_NET_READ_INTERRUPTED)
4209 *suppress_warnings = true; // Suppress reconnect warning
4210 else
4211 LogErr(ERROR_LEVEL, ER_RPL_SLAVE_ERROR_RETRYING,
4212 Command_names::str_global(command).c_str(), err,
4213 mysql_error(mysql), mi->connect_retry);
4214 if (is_network_error(err)) mi->set_network_error();
4215 return 1;
4216 }
4217
4218 7033 return 0;
4219 7033 }
4220
4221 /**
4222 Read one event from the master.
4223
4224 @param mysql MySQL connection.
4225 @param rpl Replication stream information.
4226 @param mi Master connection information.
4227 @param suppress_warnings true when a normal net read timeout has caused us
4228 to try a reconnect. We do not want to print
4229 anything to the error log in this case because
4230 this an abnormal event in an idle server.
4231
4232 @retval 'packet_error' Error.
4233 @retval number Length of packet.
4234 */
4235
4236 1349385 static ulong read_event(MYSQL *mysql, MYSQL_RPL *rpl, Master_info *mi,
4237 bool *suppress_warnings) {
4238
1/2
✓ Branch 0 taken 1349386 times.
✗ Branch 1 not taken.
1349385 DBUG_TRACE;
4239
4240 1349386 *suppress_warnings = false;
4241 /*
4242 my_real_read() will time us out
4243 We check if we were told to die, and if not, try reading again
4244 */
4245 #ifndef NDEBUG
4246
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 1349386 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1349386 times.
1349386 if (disconnect_slave_event_count && !(mi->events_until_exit--))
4247 return packet_error;
4248 #endif
4249
4250
3/4
✓ Branch 0 taken 1349240 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6613 times.
✓ Branch 3 taken 1342627 times.
1349386 if (mysql_binlog_fetch(mysql, rpl)) {
4251
1/2
✓ Branch 0 taken 6613 times.
✗ Branch 1 not taken.
6613 uint err{mysql_errno(mysql)};
4252
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6613 times.
6613 if (err == ER_NET_READ_INTERRUPTED) {
4253 /*
4254 We are trying a normal reconnect after a read timeout;
4255 we suppress prints to .err file as long as the reconnect
4256 happens without problems
4257 */
4258 *suppress_warnings = true;
4259
2/2
✓ Branch 0 taken 271 times.
✓ Branch 1 taken 6342 times.
6613 } else if (!mi->abort_slave) {
4260
10/20
✓ Branch 0 taken 271 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 271 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 271 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 271 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 271 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 271 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 271 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 271 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 271 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 271 times.
✗ Branch 19 not taken.
271 LogErr(ERROR_LEVEL, ER_RPL_SLAVE_ERROR_READING_FROM_SERVER,
4261 mi->get_for_channel_str(), mysql_error(mysql), err);
4262 }
4263
3/4
✓ Branch 0 taken 6613 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6369 times.
✓ Branch 3 taken 244 times.
6613 if (is_network_error(err)) mi->set_network_error();
4264 6613 return packet_error;
4265 }
4266
4267 /* Check if eof packet */
4268
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 1342567 times.
1342627 if (rpl->size == 0) {
4269
10/20
✓ Branch 0 taken 60 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 60 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 60 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 60 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 60 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 60 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 60 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 60 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 60 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 60 times.
✗ Branch 19 not taken.
60 LogErr(SYSTEM_LEVEL, ER_RPL_SLAVE_DUMP_THREAD_KILLED_BY_MASTER,
4270 mi->get_for_channel_str(), ::server_uuid, mysql_error(mysql));
4271 60 return packet_error;
4272 }
4273
4274
3/8
✓ Branch 0 taken 1342567 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1342566 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1342566 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
1342567 DBUG_PRINT("exit", ("len: %lu net->read_pos[4]: %d", rpl->size,
4275 mysql->net.read_pos[4]));
4276 1342566 return rpl->size - 1;
4277 1349239 }
4278
4279 /**
4280 If this is a lagging slave (specified with CHANGE MASTER TO MASTER_DELAY = X),
4281 delays accordingly. Also unlocks rli->data_lock.
4282
4283 Design note: this is the place to unlock rli->data_lock. The lock
4284 must be held when reading delay info from rli, but it should not be
4285 held while sleeping.
4286
4287 @param ev Event that is about to be executed.
4288
4289 @param thd The sql thread's THD object.
4290
4291 @param rli The sql thread's Relay_log_info structure.
4292
4293 @retval 0 If the delay timed out and the event shall be executed.
4294
4295 @retval nonzero If the delay was interrupted and the event shall be skipped.
4296 */
4297 1598429 static int sql_delay_event(Log_event *ev, THD *thd, Relay_log_info *rli) {
4298 1598429 time_t sql_delay = rli->get_sql_delay();
4299
4300
1/2
✓ Branch 0 taken 1598430 times.
✗ Branch 1 not taken.
1598429 DBUG_TRACE;
4301 mysql_mutex_assert_owner(&rli->data_lock);
4302
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1598429 times.
1598430 assert(!rli->belongs_to_client());
4303
4304
2/2
✓ Branch 0 taken 824 times.
✓ Branch 1 taken 1597605 times.
1598429 if (sql_delay) {
4305 824 int type = ev->get_type_code();
4306 824 time_t sql_delay_end = 0;
4307
4308
3/4
✓ Branch 0 taken 824 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 77 times.
✓ Branch 3 taken 747 times.
824 if (DBUG_EVALUATE_IF("sql_delay_without_timestamps", 1, 0)) {
4309 77 rli->commit_timestamps_status = Relay_log_info::COMMIT_TS_NOT_FOUND;
4310 }
4311
4/4
✓ Branch 0 taken 195 times.
✓ Branch 1 taken 629 times.
✓ Branch 2 taken 171 times.
✓ Branch 3 taken 24 times.
824 if (rli->commit_timestamps_status == Relay_log_info::COMMIT_TS_UNKNOWN &&
4312
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 169 times.
171 (type == binary_log::GTID_LOG_EVENT ||
4313 type == binary_log::ANONYMOUS_GTID_LOG_EVENT)) {
4314
2/4
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 26 times.
✗ Branch 3 not taken.
26 if (static_cast<Gtid_log_event *>(ev)->has_commit_timestamps) {
4315 26 rli->commit_timestamps_status = Relay_log_info::COMMIT_TS_FOUND;
4316 } else {
4317 rli->commit_timestamps_status = Relay_log_info::COMMIT_TS_NOT_FOUND;
4318 }
4319 }
4320
4321
2/2
✓ Branch 0 taken 578 times.
✓ Branch 1 taken 246 times.
824 if (rli->commit_timestamps_status == Relay_log_info::COMMIT_TS_FOUND) {
4322
4/4
✓ Branch 0 taken 439 times.
✓ Branch 1 taken 139 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 435 times.
578 if (type == binary_log::GTID_LOG_EVENT ||
4323 type == binary_log::ANONYMOUS_GTID_LOG_EVENT) {
4324 /*
4325 Calculate when we should execute the event.
4326 The immediate master timestamp is expressed in microseconds.
4327 Delayed replication is defined in seconds.
4328 Hence convert immediate_commit_timestamp to seconds here.
4329 */
4330
1/2
✓ Branch 0 taken 143 times.
✗ Branch 1 not taken.
143 sql_delay_end = ceil((static_cast<Gtid_log_event *>(ev)
4331 143 ->immediate_commit_timestamp) /
4332 143 1000000.00) +
4333 sql_delay;
4334 }
4335 } else {
4336 /*
4337 the immediate master does not support commit timestamps
4338 in Gtid_log_events
4339 */
4340
4/4
✓ Branch 0 taken 179 times.
✓ Branch 1 taken 67 times.
✓ Branch 2 taken 74 times.
✓ Branch 3 taken 105 times.
246 if (type != binary_log::ROTATE_EVENT &&
4341
1/2
✓ Branch 0 taken 74 times.
✗ Branch 1 not taken.
74 type != binary_log::FORMAT_DESCRIPTION_EVENT &&
4342
1/2
✓ Branch 0 taken 74 times.
✗ Branch 1 not taken.
74 type != binary_log::PREVIOUS_GTIDS_LOG_EVENT &&
4343 type != binary_log::START_5_7_ENCRYPTION_EVENT) {
4344 // Calculate when we should execute the event.
4345 74 sql_delay_end = ev->common_header->when.tv_sec +
4346 74 rli->mi->clock_diff_with_master + sql_delay;
4347 }
4348 }
4349
2/2
✓ Branch 0 taken 217 times.
✓ Branch 1 taken 607 times.
824 if (sql_delay_end != 0) {
4350 // The current time.
4351 217 time_t now = time(nullptr);
4352 // The amount of time we will have to sleep before executing the event.
4353 217 time_t nap_time = 0;
4354
4355
2/2
✓ Branch 0 taken 160 times.
✓ Branch 1 taken 57 times.
217 if (sql_delay_end > now) {
4356 160 nap_time = sql_delay_end - now;
4357
4358
3/8
✓ Branch 0 taken 160 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 160 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 160 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
160 DBUG_PRINT("info",
4359 ("sql_delay= %lu "
4360 "now= %ld "
4361 "sql_delay_end= %ld "
4362 "nap_time= %ld",
4363 sql_delay, (long)now, (long)sql_delay_end, (long)nap_time));
4364
3/8
✓ Branch 0 taken 160 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 160 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 160 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
160 DBUG_PRINT("info", ("delaying replication event %lu secs", nap_time));
4365
1/2
✓ Branch 0 taken 160 times.
✗ Branch 1 not taken.
160 rli->start_sql_delay(sql_delay_end);
4366
1/2
✓ Branch 0 taken 160 times.
✗ Branch 1 not taken.
160 mysql_mutex_unlock(&rli->data_lock);
4367
1/2
✓ Branch 0 taken 160 times.
✗ Branch 1 not taken.
160 return slave_sleep(thd, nap_time, sql_slave_killed, rli);
4368 } else {
4369
3/8
✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 57 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 57 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
57 DBUG_PRINT("info", ("sql_delay= %lu "
4370 "now= %ld "
4371 "sql_delay_end= %ld ",
4372 sql_delay, (long)now, (long)sql_delay_end));
4373 }
4374 }
4375 }
4376
1/2
✓ Branch 0 taken 1598270 times.
✗ Branch 1 not taken.
1598269 mysql_mutex_unlock(&rli->data_lock);
4377 1598270 return 0;
4378 1598430 }
4379
4380 /**
4381 Applies the given event and advances the relay log position.
4382
4383 This is needed by the sql thread to execute events from the binlog,
4384 and by clients executing BINLOG statements. Conceptually, this
4385 function does:
4386
4387 @code
4388 ev->apply_event(rli);
4389 ev->update_pos(rli);
4390 @endcode
4391
4392 It also does the following maintenance:
4393
4394 - Initializes the thread's server_id and time; and the event's
4395 thread.
4396
4397 - If !rli->belongs_to_client() (i.e., if it belongs to the slave
4398 sql thread instead of being used for executing BINLOG
4399 statements), it does the following things: (1) skips events if it
4400 is needed according to the server id or slave_skip_counter; (2)
4401 unlocks rli->data_lock; (3) sleeps if required by 'CHANGE MASTER
4402 TO MASTER_DELAY=X'; (4) maintains the running state of the sql
4403 thread (rli->thread_state).
4404
4405 - Reports errors as needed.
4406
4407 @param ptr_ev a pointer to a reference to the event to apply.
4408
4409 @param thd The client thread that executes the event (i.e., the
4410 slave sql thread if called from a replication slave, or the client
4411 thread if called to execute a BINLOG statement).
4412
4413 @param rli The relay log info (i.e., the slave's rli if called from
4414 a replication slave, or the client's thd->rli_fake if called to
4415 execute a BINLOG statement).
4416
4417 @note MTS can store NULL to @c ptr_ev location to indicate
4418 the event is taken over by a Worker.
4419
4420 @retval SLAVE_APPLY_EVENT_AND_UPDATE_POS_OK
4421 OK.
4422
4423 @retval SLAVE_APPLY_EVENT_AND_UPDATE_POS_APPLY_ERROR
4424 Error calling ev->apply_event().
4425
4426 @retval SLAVE_APPLY_EVENT_AND_UPDATE_POS_UPDATE_POS_ERROR
4427 No error calling ev->apply_event(), but error calling
4428 ev->update_pos().
4429
4430 @retval SLAVE_APPLY_EVENT_AND_UPDATE_POS_APPEND_JOB_ERROR
4431 append_item_to_jobs() failed, thread was killed while waiting
4432 for successful enqueue on worker.
4433 */
4434 static enum enum_slave_apply_event_and_update_pos_retval
4435 1649583 apply_event_and_update_pos(Log_event **ptr_ev, THD *thd, Relay_log_info *rli) {
4436 1649583 int exec_res = 0;
4437 1649583 bool skip_event = false;
4438 1649583 Log_event *ev = *ptr_ev;
4439 1649583 Log_event::enum_skip_reason reason = Log_event::EVENT_SKIP_NOT;
4440
4441
1/2
✓ Branch 0 taken 1649583 times.
✗ Branch 1 not taken.
1649583 DBUG_TRACE;
4442
4443
3/10
✓ Branch 0 taken 1649583 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1649583 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1649583 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
1649583 DBUG_PRINT("exec_event",
4444 ("%s(type_code: %d; server_id: %d)", ev->get_type_str(),
4445 ev->get_type_code(), ev->server_id));
4446
3/12
✓ Branch 0 taken 1649583 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1649583 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1649583 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
1649583 DBUG_PRINT("info",
4447 ("thd->options: %s%s; rli->last_event_start_time: %lu",
4448 FLAGSTR(thd->variables.option_bits, OPTION_NOT_AUTOCOMMIT),
4449 FLAGSTR(thd->variables.option_bits, OPTION_BEGIN),
4450 (ulong)rli->last_event_start_time));
4451
4452 /*
4453 Execute the event to change the database and update the binary
4454 log coordinates, but first we set some data that is needed for
4455 the thread.
4456
4457 The event will be executed unless it is supposed to be skipped.
4458
4459 Queries originating from this server must be skipped. Low-level
4460 events (Format_description_log_event, Rotate_log_event,
4461 Stop_log_event) from this server must also be skipped. But for
4462 those we don't want to modify 'group_master_log_pos', because
4463 these events did not exist on the master.
4464 Format_description_log_event is not completely skipped.
4465
4466 Skip queries specified by the user in 'slave_skip_counter'. We
4467 can't however skip events that has something to do with the log
4468 files themselves.
4469
4470 Filtering on own server id is extremely important, to ignore
4471 execution of events created by the creation/rotation of the relay
4472 log (remember that now the relay log starts with its Format_desc,
4473 has a Rotate etc).
4474 */
4475 /*
4476 Set the unmasked and actual server ids from the event
4477 */
4478 1649583 thd->server_id = ev->server_id; // use the original server id for logging
4479 1649583 thd->unmasked_server_id = ev->common_header->unmasked_server_id;
4480
1/2
✓ Branch 0 taken 1649583 times.
✗ Branch 1 not taken.
1649583 thd->set_time(); // time the query
4481
1/2
✓ Branch 0 taken 1649583 times.
✗ Branch 1 not taken.
1649583 thd->lex->set_current_query_block(nullptr);
4482
2/2
✓ Branch 0 taken 13794 times.
✓ Branch 1 taken 1635789 times.
1649583 if (!ev->common_header->when.tv_sec)
4483 13794 my_micro_time_to_timeval(my_micro_time(), &ev->common_header->when);
4484 1649583 ev->thd = thd; // because up to this point, ev->thd == 0
4485
4486
4/4
✓ Branch 0 taken 1205 times.
✓ Branch 1 taken 1648378 times.
✓ Branch 2 taken 1648489 times.
✓ Branch 3 taken 1094 times.
1650788 if (!(rli->is_mts_recovery() &&
4487
2/2
✓ Branch 0 taken 111 times.
✓ Branch 1 taken 1094 times.
1205 bitmap_is_set(&rli->recovery_groups, rli->mts_recovery_index))) {
4488
1/2
✓ Branch 0 taken 1648489 times.
✗ Branch 1 not taken.
1648489 reason = ev->shall_skip(rli);
4489 }
4490 #ifndef NDEBUG
4491
2/2
✓ Branch 0 taken 1205 times.
✓ Branch 1 taken 1648378 times.
1649583 if (rli->is_mts_recovery()) {
4492
3/10
✓ Branch 0 taken 1205 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1205 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1205 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
1205 DBUG_PRINT("mts",
4493 ("Mts is recovering %d, number of bits set %d, "
4494 "bitmap is set %d, index %lu.\n",
4495 rli->is_mts_recovery(), bitmap_bits_set(&rli->recovery_groups),
4496 bitmap_is_set(&rli->recovery_groups, rli->mts_recovery_index),
4497 rli->mts_recovery_index));
4498 }
4499 #endif
4500
2/2
✓ Branch 0 taken 411 times.
✓ Branch 1 taken 1649172 times.
1649583 if (reason == Log_event::EVENT_SKIP_COUNT) {
4501 411 --rli->slave_skip_counter;
4502 411 skip_event = true;
4503 }
4504
1/2
✓ Branch 0 taken 1649583 times.
✗ Branch 1 not taken.
1649583 set_timespec_nsec(&rli->ts_exec[0], 0);
4505 1649583 rli->stats_read_time += diff_timespec(&rli->ts_exec[0], &rli->ts_exec[1]);
4506
4507
2/2
✓ Branch 0 taken 1598430 times.
✓ Branch 1 taken 51153 times.
1649583 if (reason == Log_event::EVENT_SKIP_NOT) {
4508 // Sleeps if needed, and unlocks rli->data_lock.
4509
3/4
✓ Branch 0 taken 1598430 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 1598427 times.
1598430 if (sql_delay_event(ev, thd, rli))
4510 3 return SLAVE_APPLY_EVENT_AND_UPDATE_POS_OK;
4511
4512
1/2
✓ Branch 0 taken 1598217 times.
✗ Branch 1 not taken.
1598427 exec_res = ev->apply_event(rli);
4513
4514 #ifdef WITH_WSREP
4515
1/2
✓ Branch 0 taken 1598216 times.
✗ Branch 1 not taken.
1598217 mysql_mutex_lock(&thd->LOCK_wsrep_thd);
4516
4/6
✓ Branch 0 taken 127 times.
✓ Branch 1 taken 1598089 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 128 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1598217 times.
1598344 if (exec_res &&
4517 127 thd->wsrep_trx().state() != wsrep::transaction::s_executing) {
4518 WSREP_DEBUG("Apply Event failed (Reason: %d, Conflict-State: %s)",
4519 exec_res, wsrep_thd_client_state_str(thd));
4520 rli->abort_slave = 1;
4521 rli->report(ERROR_LEVEL, ER_UNKNOWN_COM_ERROR,
4522 "Node has dropped from cluster");
4523 }
4524
1/2
✓ Branch 0 taken 1598217 times.
✗ Branch 1 not taken.
1598217 mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
4525 #endif /* WITH_WSREP */
4526
4527
8/10
✓ Branch 0 taken 1598217 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 1598212 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 3 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
1598217 DBUG_EXECUTE_IF("simulate_stop_when_mta_in_group",
4528 if (rli->mts_group_status == Relay_log_info::MTS_IN_GROUP &&
4529 rli->curr_group_seen_begin)
4530 DBUG_SET("+d,stop_when_mta_in_group"););
4531
4532
4/4
✓ Branch 0 taken 1598090 times.
✓ Branch 1 taken 127 times.
✓ Branch 2 taken 1510949 times.
✓ Branch 3 taken 87141 times.
1598217 if (!exec_res && (ev->worker != rli)) {
4533
2/2
✓ Branch 0 taken 980466 times.
✓ Branch 1 taken 530483 times.
1510949 if (ev->worker) {
4534 980466 Slave_job_item item = {ev, rli->get_event_relay_log_number(),
4535 980466 rli->get_event_start_pos()};
4536 980466 Slave_job_item *job_item = &item;
4537 980466 Slave_worker *w = (Slave_worker *)ev->worker;
4538 // specially marked group typically with OVER_MAX_DBS_IN_EVENT_MTS db:s
4539 980466 bool need_sync = ev->is_mts_group_isolated();
4540
4541 // all events except BEGIN-query must be marked with a non-NULL Worker
4542
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 980466 times.
980466 assert(((Slave_worker *)ev->worker) == rli->last_assigned_worker);
4543
4544
3/8
✓ Branch 0 taken 980466 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 980466 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 980466 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
980466 DBUG_PRINT("Log_event::apply_event:",
4545 ("-> job item data %p to W_%lu", job_item->data, w->id));
4546
4547 // Reset mts in-group state
4548
2/2
✓ Branch 0 taken 282116 times.
✓ Branch 1 taken 698350 times.
980466 if (rli->mts_group_status == Relay_log_info::MTS_END_GROUP) {
4549 // CGAP cleanup
4550
1/2
✓ Branch 0 taken 282115 times.
✗ Branch 1 not taken.
282116 rli->curr_group_assigned_parts.clear();
4551 // reset the B-group and Gtid-group marker
4552 282115 rli->curr_group_seen_begin = rli->curr_group_seen_gtid = false;
4553 282115 rli->last_assigned_worker = nullptr;
4554 }
4555 /*
4556 Storing GAQ index of the group that the event belongs to
4557 in the event. Deferred events are handled similarly below.
4558 */
4559 980465 ev->mts_group_idx = rli->gaq->assigned_group_index;
4560
4561 980465 bool append_item_to_jobs_error = false;
4562
3/4
✓ Branch 0 taken 980466 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 282026 times.
✓ Branch 3 taken 698440 times.
980465 if (rli->curr_group_da.size() > 0) {
4563 /*
4564 the current event sorted out which partition the current group
4565 belongs to. It's time now to processed deferred array events.
4566 */
4567
3/4
✓ Branch 0 taken 812464 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 530438 times.
✓ Branch 3 taken 282026 times.
812464 for (uint i = 0; i < rli->curr_group_da.size(); i++) {
4568
1/2
✓ Branch 0 taken 530438 times.
✗ Branch 1 not taken.
530438 Slave_job_item da_item = rli->curr_group_da[i];
4569
3/8
✓ Branch 0 taken 530438 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 530438 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 530438 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
530438 DBUG_PRINT("mts", ("Assigning job %llu to worker %lu",
4570 (da_item.data)->common_header->log_pos, w->id));
4571 530438 da_item.data->mts_group_idx =
4572 530438 rli->gaq->assigned_group_index; // similarly to above
4573
2/2
✓ Branch 0 taken 530437 times.
✓ Branch 1 taken 1 times.
530438 if (!append_item_to_jobs_error)
4574
1/2
✓ Branch 0 taken 530437 times.
✗ Branch 1 not taken.
530437 append_item_to_jobs_error = append_item_to_jobs(&da_item, w, rli);
4575
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 530436 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
530438 if (append_item_to_jobs_error) delete da_item.data;
4576 }
4577
1/2
✓ Branch 0 taken 282026 times.
✗ Branch 1 not taken.
282026 rli->curr_group_da.clear();
4578 }
4579
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 980465 times.
980466 if (append_item_to_jobs_error)
4580 1 return SLAVE_APPLY_EVENT_AND_UPDATE_POS_APPEND_JOB_ERROR;
4581
4582
3/8
✓ Branch 0 taken 980464 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 980465 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 980465 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
980465 DBUG_PRINT("mts", ("Assigning job %llu to worker %lu\n",
4583 job_item->data->common_header->log_pos, w->id));
4584
4585 /* Notice `ev' instance can be destroyed after `append()' */
4586
2/4
✓ Branch 0 taken 980465 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 980465 times.
980465 if (append_item_to_jobs(job_item, w, rli))
4587 return SLAVE_APPLY_EVENT_AND_UPDATE_POS_APPEND_JOB_ERROR;
4588
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 980437 times.
980465 if (need_sync) {
4589 /*
4590 combination of over-max db:s and end of the current group
4591 forces to wait for the assigned groups completion by assigned
4592 to the event worker.
4593 Indeed MTS group status could be safely set to MTS_NOT_IN_GROUP
4594 after wait_() returns.
4595 No need to know a possible error out of synchronization call.
4596 */
4597
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 (void)rli->current_mts_submode->wait_for_workers_to_finish(rli);
4598 }
4599 }
4600 1510948 *ptr_ev = nullptr; // announcing the event is passed to w-worker
4601
4602
6/8
✓ Branch 0 taken 1510947 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1510947 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 934 times.
✓ Branch 5 taken 1510013 times.
✓ Branch 6 taken 934 times.
✓ Branch 7 taken 1510013 times.
1510948 if (rli->is_parallel_exec() && rli->mts_events_assigned % 1024 == 1) {
4603 934 time_t my_now = time(nullptr);
4604
4605
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 893 times.
934 if ((my_now - rli->mts_last_online_stat) >= mts_online_stat_period) {
4606
9/18
✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 41 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 41 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 41 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 41 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 41 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 41 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 41 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 41 times.
✗ Branch 17 not taken.
82 LogErr(INFORMATION_LEVEL, ER_RPL_MTS_STATISTICS,
4607 rli->get_for_channel_str(),
4608 static_cast<unsigned long>(my_now - rli->mts_last_online_stat),
4609 rli->mts_events_assigned, rli->mts_wq_overrun_cnt,
4610 rli->mts_wq_overfill_cnt, rli->wq_size_waits_cnt,
4611 rli->mts_total_wait_overlap.load(),
4612 rli->mts_wq_no_underrun_cnt, rli->mts_total_wait_worker_avail);
4613 41 rli->mts_last_online_stat = my_now;
4614 }
4615 }
4616 }
4617 } else
4618
1/2
✓ Branch 0 taken 51153 times.
✗ Branch 1 not taken.
51153 mysql_mutex_unlock(&rli->data_lock);
4619
4620
1/2
✓ Branch 0 taken 1649368 times.
✗ Branch 1 not taken.
1649368 set_timespec_nsec(&rli->ts_exec[1], 0);
4621 1649368 rli->stats_exec_time += diff_timespec(&rli->ts_exec[1], &rli->ts_exec[0]);
4622
4623
3/8
✓ Branch 0 taken 1649369 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1649368 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1649368 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
1649369 DBUG_PRINT("info", ("apply_event error = %d", exec_res));
4624
2/2
✓ Branch 0 taken 1649241 times.
✓ Branch 1 taken 127 times.
1649368 if (exec_res == 0) {
4625 /*
4626 Positions are not updated here when an XID is processed. To make
4627 a slave crash-safe, positions must be updated while processing a
4628 XID event and as such do not need to be updated here again.
4629
4630 However, if the event needs to be skipped, this means that it
4631 will not be processed and then positions need to be updated here.
4632
4633 DDL:s that are not yet committed, as indicated by
4634 @c has_ddl_committed flag, visit the block.
4635
4636 See sql/rpl_rli.h for further details.
4637 */
4638 1649241 int error = 0;
4639
6/6
✓ Branch 0 taken 138294 times.
✓ Branch 1 taken 1510947 times.
✓ Branch 2 taken 137541 times.
✓ Branch 3 taken 753 times.
✓ Branch 4 taken 137944 times.
✓ Branch 5 taken 1511297 times.
1925829 if (*ptr_ev &&
4640 138294 ((ev->get_type_code() != binary_log::XID_EVENT &&
4641
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 137541 times.
✓ Branch 2 taken 475 times.
✓ Branch 3 taken 278 times.
138294 !is_committed_ddl(*ptr_ev)) ||
4642
2/2
✓ Branch 0 taken 141 times.
✓ Branch 1 taken 334 times.
475 skip_event ||
4643
1/2
✓ Branch 0 taken 141 times.
✗ Branch 1 not taken.
616 (rli->is_mts_recovery() && !is_gtid_event(ev) &&
4644
4/8
✓ Branch 0 taken 141 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 141 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 125 times.
✓ Branch 7 taken 16 times.
282 (ev->ends_group() || !rli->mts_recovery_group_seen_begin) &&
4645 141 bitmap_is_set(&rli->recovery_groups, rli->mts_recovery_index)))) {
4646 #ifndef NDEBUG
4647 /*
4648 This only prints information to the debug trace.
4649
4650 TODO: Print an informational message to the error log?
4651 */
4652 static const char *const explain[] = {
4653 // EVENT_SKIP_NOT,
4654 "not skipped",
4655 // EVENT_SKIP_IGNORE,
4656 "skipped because event should be ignored",
4657 // EVENT_SKIP_COUNT
4658 "skipped because event skip counter was non-zero"};
4659
3/8
✓ Branch 0 taken 137944 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 137944 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 137944 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
137944 DBUG_PRINT("info",
4660 ("OPTION_BEGIN: %d; IN_STMT: %d",
4661 static_cast<bool>(thd->variables.option_bits & OPTION_BEGIN),
4662 rli->get_flag(Relay_log_info::IN_STMT)));
4663
3/10
✓ Branch 0 taken 137944 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 137944 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 137944 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
137944 DBUG_PRINT("skip_event",
4664 ("%s event was %s", ev->get_type_str(), explain[reason]));
4665 #endif
4666
4667
1/2
✓ Branch 0 taken 137944 times.
✗ Branch 1 not taken.
137944 error = ev->update_pos(rli);
4668 /*
4669 Slave skips an event if the slave_skip_counter is greater than zero.
4670 We have to free thd's mem_root here after we update the positions
4671 in the repository table if the event is a skipped event.
4672 Otherwise, imagine a situation where slave_skip_counter is big number
4673 and slave is skipping the events and updating the repository.
4674 All the memory used while these operations are going on is never
4675 freed unless slave starts executing the events (after slave_skip_counter
4676 becomes zero).
4677
4678 Hence we free thd's mem_root here if it is a skipped event.
4679 (freeing mem_root generally happens from Query_log_event::do_apply_event
4680 or Rows_log_event::do_apply_event when they find the end of
4681 the group event).
4682 */
4683
3/4
✓ Branch 0 taken 411 times.
✓ Branch 1 taken 137533 times.
✓ Branch 2 taken 411 times.
✗ Branch 3 not taken.
137944 if (skip_event) thd->mem_root->ClearForReuse();
4684
4685 #ifndef NDEBUG
4686
3/8
✓ Branch 0 taken 137944 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 137944 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 137944 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
137944 DBUG_PRINT("info", ("update_pos error = %d", error));
4687
1/2
✓ Branch 0 taken 137944 times.
✗ Branch 1 not taken.
137944 if (!rli->belongs_to_client()) {
4688 char buf[22];
4689
3/10
✓ Branch 0 taken 137944 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 137944 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 137944 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
137944 DBUG_PRINT("info",
4690 ("group %s %s", llstr(rli->get_group_relay_log_pos(), buf),
4691 rli->get_group_relay_log_name()));
4692
3/10
✓ Branch 0 taken 137944 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 137944 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 137944 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
137944 DBUG_PRINT("info",
4693 ("event %s %s", llstr(rli->get_event_relay_log_pos(), buf),
4694 rli->get_event_relay_log_name()));
4695 }
4696 #endif
4697 } else {
4698 /*
4699 INTVAR_EVENT, RAND_EVENT, USER_VAR_EVENT and ROWS_QUERY_LOG_EVENT are
4700 deferred event. It means ev->worker is NULL.
4701 */
4702
4/16
✓ Branch 0 taken 1510947 times.
✓ Branch 1 taken 350 times.
✓ Branch 2 taken 1510947 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1510947 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
1511297 assert(*ptr_ev == ev || rli->is_parallel_exec() ||
4703 (!ev->worker &&
4704 (ev->get_type_code() == binary_log::INTVAR_EVENT ||
4705 ev->get_type_code() == binary_log::RAND_EVENT ||
4706 ev->get_type_code() == binary_log::USER_VAR_EVENT ||
4707 ev->get_type_code() == binary_log::ROWS_QUERY_LOG_EVENT)));
4708
4709 1511297 rli->inc_event_relay_log_pos();
4710 }
4711
4712
4/4
✓ Branch 0 taken 1204 times.
✓ Branch 1 taken 1648037 times.
✓ Branch 2 taken 1187 times.
✓ Branch 3 taken 17 times.
1650445 if (!error && rli->is_mts_recovery() &&
4713
2/2
✓ Branch 0 taken 1153 times.
✓ Branch 1 taken 34 times.
2391 ev->get_type_code() != binary_log::ROTATE_EVENT &&
4714
2/2
✓ Branch 0 taken 1136 times.
✓ Branch 1 taken 17 times.
2340 ev->get_type_code() != binary_log::FORMAT_DESCRIPTION_EVENT &&
4715
4/6
✓ Branch 0 taken 1649241 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1136 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1136 times.
✓ Branch 5 taken 1648105 times.
3299635 ev->get_type_code() != binary_log::PREVIOUS_GTIDS_LOG_EVENT &&
4716 1136 ev->get_type_code() != binary_log::START_5_7_ENCRYPTION_EVENT) {
4717
3/4
✓ Branch 0 taken 1136 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 164 times.
✓ Branch 3 taken 972 times.
1136 if (ev->starts_group()) {
4718 164 rli->mts_recovery_group_seen_begin = true;
4719
7/8
✓ Branch 0 taken 972 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 806 times.
✓ Branch 3 taken 166 times.
✓ Branch 4 taken 394 times.
✓ Branch 5 taken 412 times.
✓ Branch 6 taken 281 times.
✓ Branch 7 taken 691 times.
1532 } else if ((ev->ends_group() || !rli->mts_recovery_group_seen_begin) &&
4720
2/2
✓ Branch 0 taken 281 times.
✓ Branch 1 taken 279 times.
560 !is_gtid_event(ev)) {
4721 281 rli->mts_recovery_index++;
4722
2/2
✓ Branch 0 taken 223 times.
✓ Branch 1 taken 58 times.
281 if (--rli->mts_recovery_group_cnt == 0) {
4723 223 rli->mts_recovery_index = 0;
4724
9/18
✓ Branch 0 taken 223 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 223 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 223 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 223 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 223 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 223 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 223 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 223 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 223 times.
✗ Branch 17 not taken.
223 LogErr(INFORMATION_LEVEL, ER_RPL_MTS_RECOVERY_COMPLETE,
4725 rli->get_for_channel_str(), rli->get_group_relay_log_name(),
4726 rli->get_group_relay_log_pos(),
4727 rli->get_group_master_log_name(),
4728 rli->get_group_master_log_pos());
4729 /*
4730 Few tests wait for UNTIL_SQL_AFTER_MTS_GAPS completion.
4731 Due to existing convention the status won't change
4732 prior to slave restarts.
4733 So making of UNTIL_SQL_AFTER_MTS_GAPS completion is done here,
4734 and only in the debug build to make the test to catch the change
4735 despite a faulty design of UNTIL checking before execution.
4736 */
4737
2/2
✓ Branch 0 taken 82 times.
✓ Branch 1 taken 141 times.
223 if (rli->until_condition ==
4738 Relay_log_info::UNTIL_SQL_AFTER_MTS_GAPS) {
4739 82 rli->until_condition = Relay_log_info::UNTIL_DONE;
4740 }
4741 // reset the Worker tables to remove last slave session time info
4742
2/4
✓ Branch 0 taken 223 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 223 times.
223 if ((error = rli->mts_finalize_recovery())) {
4743 (void)Rpl_info_factory::reset_workers(rli);
4744 }
4745 }
4746 281 rli->mts_recovery_group_seen_begin = false;
4747
1/2
✓ Branch 0 taken 281 times.
✗ Branch 1 not taken.
281 if (!error)
4748
1/2
✓ Branch 0 taken 281 times.
✗ Branch 1 not taken.
281 error = rli->flush_info(Relay_log_info::RLI_FLUSH_IGNORE_SYNC_OPT);
4749 }
4750 }
4751
4752
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1649241 times.
1649241 if (error) {
4753 /*
4754 The update should not fail, so print an error message and
4755 return an error code.
4756
4757 TODO: Replace this with a decent error message when merged
4758 with BUG#24954 (which adds several new error message).
4759 */
4760 char buf[22];
4761 rli->report(ERROR_LEVEL, ER_UNKNOWN_ERROR,
4762 "It was not possible to update the positions"
4763 " of the relay log information: the slave may"
4764 " be in an inconsistent state."
4765 " Stopped in %s position %s",
4766 rli->get_group_relay_log_name(),
4767 llstr(rli->get_group_relay_log_pos(), buf));
4768 return SLAVE_APPLY_EVENT_AND_UPDATE_POS_UPDATE_POS_ERROR;
4769 }
4770 }
4771
4772
2/2
✓ Branch 0 taken 127 times.
✓ Branch 1 taken 1649241 times.
1649368 return exec_res ? SLAVE_APPLY_EVENT_AND_UPDATE_POS_APPLY_ERROR
4773 1649368 : SLAVE_APPLY_EVENT_AND_UPDATE_POS_OK;
4774 1649372 }
4775
4776 /**
4777 Let the worker applying the current group to rollback and gracefully
4778 finish its work before.
4779
4780 @param rli The slave's relay log info.
4781
4782 @param ev a pointer to the event on hold before applying this rollback
4783 procedure.
4784
4785 @retval false The rollback succeeded.
4786
4787 @retval true There was an error while injecting events.
4788 */
4789 41 static bool coord_handle_partial_binlogged_transaction(Relay_log_info *rli,
4790 const Log_event *ev) {
4791
1/2
✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
41 DBUG_TRACE;
4792 /*
4793 This function is called holding the rli->data_lock.
4794 We must return it still holding this lock, except in the case of returning
4795 error.
4796 */
4797 mysql_mutex_assert_owner(&rli->data_lock);
4798 41 THD *thd = rli->info_thd;
4799
4800
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 29 times.
41 if (!rli->curr_group_seen_begin) {
4801
3/8
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 12 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
12 DBUG_PRINT("info", ("Injecting QUERY(BEGIN) to rollback worker"));
4802 Log_event *begin_event = new Query_log_event(thd, STRING_WITH_LEN("BEGIN"),
4803 true, /* using_trans */
4804 false, /* immediate */
4805 true, /* suppress_use */
4806 0, /* error */
4807
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 true /* ignore_command */);
4808 12 ((Query_log_event *)begin_event)->db = "";
4809 12 begin_event->common_header->data_written = 0;
4810 12 begin_event->server_id = ev->server_id;
4811 /*
4812 This event is not generated on master and is only specific to replicas.
4813 So, we don't want this BEGIN query to respect MASTER_DELAY.
4814 Make the timestamp to be same as that of the FORMAT_DESCRIPTION_EVENT
4815 event which triggered this.
4816 */
4817 12 begin_event->common_header->when = ev->common_header->when;
4818 /*
4819 We must be careful to avoid SQL thread increasing its position
4820 farther than the event that triggered this QUERY(BEGIN).
4821 */
4822 12 begin_event->common_header->log_pos = ev->common_header->log_pos;
4823 12 begin_event->future_event_relay_log_pos = ev->future_event_relay_log_pos;
4824
4825
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
12 if (apply_event_and_update_pos(&begin_event, thd, rli) !=
4826 SLAVE_APPLY_EVENT_AND_UPDATE_POS_OK) {
4827 delete begin_event;
4828 return true;
4829 }
4830
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 mysql_mutex_lock(&rli->data_lock);
4831 }
4832
4833
3/8
✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 41 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 41 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
41 DBUG_PRINT("info", ("Injecting QUERY(ROLLBACK) to rollback worker"));
4834 Log_event *rollback_event = new Query_log_event(
4835 thd, STRING_WITH_LEN("ROLLBACK"), true, /* using_trans */
4836 false, /* immediate */
4837 true, /* suppress_use */
4838 0, /* error */
4839
2/4
✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 41 times.
✗ Branch 3 not taken.
41 true /* ignore_command */);
4840 41 ((Query_log_event *)rollback_event)->db = "";
4841 41 rollback_event->common_header->data_written = 0;
4842 41 rollback_event->server_id = ev->server_id;
4843 /*
4844 This event is not generated on master and is only specific to replicas.
4845 So, we don't want this ROLLBACK query to respect MASTER_DELAY.
4846 Make the timestamp to be same as that of the FORMAT_DESCRIPTION_EVENT
4847 event which triggered this.
4848 */
4849 41 rollback_event->common_header->when = ev->common_header->when;
4850 /*
4851 We must be careful to avoid SQL thread increasing its position
4852 farther than the event that triggered this QUERY(ROLLBACK).
4853 */
4854 41 rollback_event->common_header->log_pos = ev->common_header->log_pos;
4855 41 rollback_event->future_event_relay_log_pos = ev->future_event_relay_log_pos;
4856
4857 41 ((Query_log_event *)rollback_event)->rollback_injected_by_coord = true;
4858
4859
2/4
✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 41 times.
41 if (apply_event_and_update_pos(&rollback_event, thd, rli) !=
4860 SLAVE_APPLY_EVENT_AND_UPDATE_POS_OK) {
4861 delete rollback_event;
4862 return true;
4863 }
4864
1/2
✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
41 mysql_mutex_lock(&rli->data_lock);
4865
4866 41 return false;
4867 41 }
4868
4869 /**
4870 Top-level function for executing the next event in the relay log.
4871 This is called from the SQL thread.
4872
4873 This function reads the event from the relay log, executes it, and
4874 advances the relay log position. It also handles errors, etc.
4875
4876 This function may fail to apply the event for the following reasons:
4877
4878 - The position specified by the UNTIL condition of the START SLAVE
4879 command is reached.
4880
4881 - It was not possible to read the event from the log.
4882
4883 - The slave is killed.
4884
4885 - An error occurred when applying the event, and the event has been
4886 tried slave_trans_retries times. If the event has been retried
4887 fewer times, 0 is returned.
4888
4889 - init_info or init_relay_log_pos failed. (These are called
4890 if a failure occurs when applying the event.)
4891
4892 - An error occurred when updating the binlog position.
4893
4894 @retval 0 The event was applied.
4895
4896 @retval 1 The event was not applied.
4897 */
4898 1657730 static int exec_relay_log_event(THD *thd, Relay_log_info *rli,
4899 Rpl_applier_reader *applier_reader,
4900 Log_event *in) {
4901
1/2
✓ Branch 0 taken 1657730 times.
✗ Branch 1 not taken.
1657730 DBUG_TRACE;
4902
4903 /*
4904 We acquire this mutex since we need it for all operations except
4905 event execution. But we will release it in places where we will
4906 wait for something for example inside of next_event().
4907 */
4908
1/2
✓ Branch 0 taken 1657729 times.
✗ Branch 1 not taken.
1657730 mysql_mutex_lock(&rli->data_lock);
4909
4910 1657729 Log_event *ev = nullptr;
4911 #ifndef NDEBUG
4912
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 1657729 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1657729 times.
✗ Branch 5 not taken.
1657729 if (!abort_slave_event_count || rli->events_until_exit--)
4913 #endif
4914 1657729 ev = in;
4915
4916 1657729 Log_event **ptr_ev = nullptr;
4917 1657729 RLI_current_event_raii rli_c_ev(rli, ev);
4918
4919
2/2
✓ Branch 0 taken 1649672 times.
✓ Branch 1 taken 8058 times.
1657730 if (ev != nullptr) {
4920 /*
4921 To avoid assigned event groups exceeding rli->checkpoint_group, it
4922 need force to compute checkpoint.
4923 */
4924 1649672 bool force = rli->rli_checkpoint_seqno >= rli->checkpoint_group;
4925
6/8
✓ Branch 0 taken 1649672 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1649672 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 33881 times.
✓ Branch 5 taken 1615791 times.
✓ Branch 6 taken 33881 times.
✓ Branch 7 taken 1615791 times.
1649672 if (force || rli->is_time_for_mta_checkpoint()) {
4926
1/2
✓ Branch 0 taken 33881 times.
✗ Branch 1 not taken.
33881 mysql_mutex_unlock(&rli->data_lock);
4927
2/4
✓ Branch 0 taken 33881 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 33881 times.
33881 if (mta_checkpoint_routine(rli, force)) {
4928 delete ev;
4929 return 1;
4930 }
4931
1/2
✓ Branch 0 taken 33881 times.
✗ Branch 1 not taken.
33881 mysql_mutex_lock(&rli->data_lock);
4932 }
4933 }
4934
4935 /*
4936 It should be checked after calling mta_checkpoint_routine(), because that
4937 function could be interrupted by kill while 'force' is true.
4938 */
4939
3/4
✓ Branch 0 taken 1657730 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8075 times.
✓ Branch 3 taken 1649655 times.
1657730 if (sql_slave_killed(thd, rli)) {
4940
1/2
✓ Branch 0 taken 8075 times.
✗ Branch 1 not taken.
8075 mysql_mutex_unlock(&rli->data_lock);
4941
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 8051 times.
8075 delete ev;
4942
4943
9/18
✓ Branch 0 taken 8075 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8075 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8075 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 8075 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 8075 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 8075 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 8075 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 8075 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 8075 times.
✗ Branch 17 not taken.
8075 LogErr(INFORMATION_LEVEL, ER_RPL_SLAVE_ERROR_READING_RELAY_LOG_EVENTS,
4944 rli->get_for_channel_str(), "slave SQL thread was killed");
4945 8075 return 1;
4946 }
4947
4948
2/2
✓ Branch 0 taken 1649648 times.
✓ Branch 1 taken 7 times.
1649655 if (ev) {
4949 #ifdef WITH_WSREP
4950
2/4
✓ Branch 0 taken 1649648 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1649648 times.
1649648 if (wsrep_before_statement(thd)) {
4951 mysql_mutex_unlock(&rli->data_lock);
4952 WSREP_INFO("Wsrep before statement error");
4953 return 1;
4954 }
4955 #endif /* WITH_WSREP */
4956
4957
3/4
✓ Branch 0 taken 1649648 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 308465 times.
✓ Branch 3 taken 1341183 times.
1649648 if (rli->is_row_format_required()) {
4958 308465 bool info_error{false};
4959 308465 binary_log::Log_event_basic_info log_event_info;
4960
1/2
✓ Branch 0 taken 308465 times.
✗ Branch 1 not taken.
308465 std::tie(info_error, log_event_info) = extract_log_event_basic_info(ev);
4961
4962
2/4
✓ Branch 0 taken 308465 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 308465 times.
616930 if (info_error ||
4963
2/4
✓ Branch 0 taken 308465 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 308465 times.
308465 rli->transaction_parser.feed_event(log_event_info, true)) {
4964 /* purecov: begin inspected */
4965 LogErr(WARNING_LEVEL,
4966 ER_RPL_SLAVE_SQL_THREAD_DETECTED_UNEXPECTED_EVENT_SEQUENCE);
4967 /* purecov: end */
4968 }
4969
4970
6/8
✓ Branch 0 taken 308465 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 308465 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
✓ Branch 5 taken 308458 times.
✓ Branch 6 taken 7 times.
✓ Branch 7 taken 308458 times.
308465 if (info_error || rli->transaction_parser.check_row_logging_constraints(
4971 log_event_info)) {
4972
2/4
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
7 rli->report(
4973 ERROR_LEVEL,
4974 ER_RPL_SLAVE_APPLY_LOG_EVENT_FAILED_INVALID_NON_ROW_FORMAT,
4975 ER_THD(thd,
4976 ER_RPL_SLAVE_APPLY_LOG_EVENT_FAILED_INVALID_NON_ROW_FORMAT),
4977 7 rli->mi->get_channel());
4978 7 rli->abort_slave = true;
4979
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 mysql_mutex_unlock(&rli->data_lock);
4980
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 delete ev;
4981 7 return 1;
4982 }
4983 }
4984
4985 enum enum_slave_apply_event_and_update_pos_retval exec_res;
4986
4987 1649641 ptr_ev = &ev;
4988 /*
4989 Even if we don't execute this event, we keep the master timestamp,
4990 so that seconds behind master shows correct delta (there are events
4991 that are not replayed, so we keep falling behind).
4992
4993 If it is an artificial event, or a relay log event (IO thread generated
4994 event) or ev->when is set to 0, or a FD from master, or a heartbeat
4995 event with server_id '0' then we don't update the last_master_timestamp.
4996
4997 In case of parallel execution last_master_timestamp is only updated when
4998 a job is taken out of GAQ. Thus when last_master_timestamp is 0 (which
4999 indicates that GAQ is empty, all slave workers are waiting for events from
5000 the Coordinator), we need to initialize it with a timestamp from the first
5001 event to be executed in parallel.
5002 */
5003
7/8
✓ Branch 0 taken 1649641 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1646086 times.
✓ Branch 3 taken 3555 times.
✓ Branch 4 taken 142761 times.
✓ Branch 5 taken 1503325 times.
✓ Branch 6 taken 80984 times.
✓ Branch 7 taken 1568657 times.
1795957 if ((!rli->is_parallel_exec() || rli->last_master_timestamp == 0) &&
5004
6/6
✓ Branch 0 taken 136588 times.
✓ Branch 1 taken 9728 times.
✓ Branch 2 taken 93059 times.
✓ Branch 3 taken 43529 times.
✓ Branch 4 taken 87018 times.
✓ Branch 5 taken 6041 times.
239375 !(ev->is_artificial_event() || ev->is_relay_log_event() ||
5005 93059 ev->get_type_code() == binary_log::FORMAT_DESCRIPTION_EVENT ||
5006
2/2
✓ Branch 0 taken 80984 times.
✓ Branch 1 taken 6034 times.
87018 ev->server_id == 0)) {
5007 80984 rli->last_master_timestamp =
5008 80984 ev->common_header->when.tv_sec + (time_t)ev->exec_time;
5009
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 80984 times.
80984 assert(rli->last_master_timestamp >= 0);
5010 }
5011
5012
3/4
✓ Branch 0 taken 1649641 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 109 times.
✓ Branch 3 taken 1649532 times.
1649641 if (rli->is_until_satisfied_before_dispatching_event(ev)) {
5013 /*
5014 Setting abort_slave flag because we do not want additional message about
5015 error in query execution to be printed.
5016 */
5017 109 rli->abort_slave = true;
5018
1/2
✓ Branch 0 taken 109 times.
✗ Branch 1 not taken.
109 mysql_mutex_unlock(&rli->data_lock);
5019 #ifdef WITH_WSREP
5020
1/2
✓ Branch 0 taken 109 times.
✗ Branch 1 not taken.
109 wsrep_after_statement(thd);
5021 #endif /* WITH_WSREP */
5022
1/2
✓ Branch 0 taken 109 times.
✗ Branch 1 not taken.
109 delete ev;
5023 109 return SLAVE_APPLY_EVENT_UNTIL_REACHED;
5024 }
5025
5026 {
5027 /**
5028 The following failure injecion works in cooperation
5029 with tests setting @@global.debug= 'd,incomplete_group_in_relay_log'.
5030 Xid or Commit events are not executed to force the slave sql read
5031 hanging if the relay log does not have any more events.
5032 */
5033
13/18
✓ Branch 0 taken 1649532 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 1649516 times.
✓ Branch 4 taken 14 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 8 times.
✓ Branch 7 taken 6 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 8 times.
✓ Branch 10 taken 2 times.
✓ Branch 11 taken 14 times.
✓ Branch 12 taken 2 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 2 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 2 times.
✗ Branch 17 not taken.
1649532 DBUG_EXECUTE_IF(
5034 "incomplete_group_in_relay_log",
5035 if ((ev->get_type_code() == binary_log::XID_EVENT) ||
5036 ((ev->get_type_code() == binary_log::QUERY_EVENT) &&
5037 strcmp("COMMIT", ((Query_log_event *)ev)->query) == 0)) {
5038 rli->abort_slave = 1;
5039 mysql_mutex_unlock(&rli->data_lock);
5040 #ifdef WITH_WSREP
5041 wsrep_after_statement(thd);
5042 #endif /* WITH_WSREP */
5043 delete ev;
5044 rli->inc_event_relay_log_pos();
5045 return 0;
5046 };);
5047 }
5048
5049 /*
5050 GTID protocol will put a FORMAT_DESCRIPTION_EVENT from the master with
5051 log_pos != 0 after each (re)connection if auto positioning is enabled.
5052 This means that the SQL thread might have already started to apply the
5053 current group but, as the IO thread had to reconnect, it left this
5054 group incomplete and will start it again from the beginning.
5055 So, before applying this FORMAT_DESCRIPTION_EVENT, we must let the
5056 worker roll back the current group and gracefully finish its work,
5057 before starting to apply the new (complete) copy of the group.
5058 */
5059 1649530 if (ev->get_type_code() == binary_log::FORMAT_DESCRIPTION_EVENT &&
5060
4/4
✓ Branch 0 taken 13001 times.
✓ Branch 1 taken 34941 times.
✓ Branch 2 taken 10609 times.
✓ Branch 3 taken 2392 times.
47942 ev->server_id != ::server_id && ev->common_header->log_pos != 0 &&
5061
9/10
✓ Branch 0 taken 47942 times.
✓ Branch 1 taken 1601588 times.
✓ Branch 2 taken 10609 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 10581 times.
✓ Branch 5 taken 28 times.
✓ Branch 6 taken 41 times.
✓ Branch 7 taken 10540 times.
✓ Branch 8 taken 41 times.
✓ Branch 9 taken 1649489 times.
1697472 rli->is_parallel_exec() && rli->curr_group_seen_gtid) {
5062
2/4
✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 41 times.
41 if (coord_handle_partial_binlogged_transaction(rli, ev))
5063 /*
5064 In the case of an error, coord_handle_partial_binlogged_transaction
5065 will not try to get the rli->data_lock again.
5066 */
5067 #ifdef WITH_WSREP
5068 {
5069 wsrep_after_statement(thd);
5070 #endif /* WITH_WSREP */
5071 /*
5072 In the case of an error, coord_handle_partial_binlogged_transaction
5073 will not try to get the rli->data_lock again.
5074 */
5075 return 1;
5076 #ifdef WITH_WSREP
5077 }
5078 #endif /* WITH_WSREP */
5079 }
5080
5081 /* ptr_ev can change to NULL indicating MTS coorinator passed to a Worker */
5082
1/2
✓ Branch 0 taken 1649319 times.
✗ Branch 1 not taken.
1649530 exec_res = apply_event_and_update_pos(ptr_ev, thd, rli);
5083 /*
5084 Note: the above call to apply_event_and_update_pos executes
5085 mysql_mutex_unlock(&rli->data_lock);
5086 */
5087
5088 /* For deferred events, the ptr_ev is set to NULL
5089 in Deferred_log_events::add() function.
5090 Hence deferred events won't be deleted here.
5091 They will be deleted in Deferred_log_events::rewind() function.
5092 */
5093
2/2
✓ Branch 0 taken 138425 times.
✓ Branch 1 taken 1510894 times.
1649319 if (*ptr_ev) {
5094
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 138425 times.
138425 assert(*ptr_ev == ev); // event remains to belong to Coordinator
5095
5096
6/8
✓ Branch 0 taken 138425 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 29 times.
✓ Branch 3 taken 138396 times.
✓ Branch 4 taken 7 times.
✓ Branch 5 taken 22 times.
✓ Branch 6 taken 7 times.
✗ Branch 7 not taken.
138425 DBUG_EXECUTE_IF("dbug.calculate_sbm_after_previous_gtid_log_event", {
5097 if (ev->get_type_code() == binary_log::PREVIOUS_GTIDS_LOG_EVENT) {
5098 rpl_replica_debug_point(DBUG_RPL_S_SBM_AFTER_PREVIOUS_GTID_EV, thd);
5099 }
5100 };);
5101
10/12
✓ Branch 0 taken 138425 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 51 times.
✓ Branch 3 taken 138374 times.
✓ Branch 4 taken 21 times.
✓ Branch 5 taken 30 times.
✓ Branch 6 taken 6 times.
✓ Branch 7 taken 15 times.
✓ Branch 8 taken 6 times.
✓ Branch 9 taken 45 times.
✓ Branch 10 taken 6 times.
✗ Branch 11 not taken.
138425 DBUG_EXECUTE_IF("dbug.calculate_sbm_after_fake_rotate_log_event", {
5102 if (ev->get_type_code() == binary_log::ROTATE_EVENT &&
5103 ev->is_artificial_event()) {
5104 rpl_replica_debug_point(DBUG_RPL_S_SBM_AFTER_FAKE_ROTATE_EV, thd);
5105 }
5106 };);
5107 /*
5108 Format_description_log_event should not be deleted because it will be
5109 used to read info about the relay log's format; it will be deleted when
5110 the SQL thread does not need it, i.e. when this thread terminates.
5111 ROWS_QUERY_LOG_EVENT is destroyed at the end of the current statement
5112 clean-up routine.
5113 */
5114
5/6
✓ Branch 0 taken 90483 times.
✓ Branch 1 taken 47942 times.
✓ Branch 2 taken 90483 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 90483 times.
✓ Branch 5 taken 47942 times.
228908 if (ev->get_type_code() != binary_log::FORMAT_DESCRIPTION_EVENT &&
5115 90483 ev->get_type_code() != binary_log::ROWS_QUERY_LOG_EVENT) {
5116
3/8
✓ Branch 0 taken 90483 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 90483 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 90483 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
90483 DBUG_PRINT("info", ("Deleting the event after it has been executed"));
5117
1/2
✓ Branch 0 taken 90483 times.
✗ Branch 1 not taken.
90483 delete ev;
5118 /*
5119 Raii guard is explicitly instructed to invalidate
5120 otherwise bogus association of the execution context with the being
5121 destroyed above event.
5122 */
5123 90483 ev = rli->current_event = nullptr;
5124 }
5125 }
5126
5127 /*
5128 exec_res == SLAVE_APPLY_EVENT_AND_UPDATE_POS_UPDATE_POS_ERROR
5129 update_log_pos failed: this should not happen, so we
5130 don't retry.
5131 exec_res == SLAVE_APPLY_EVENT_AND_UPDATE_POS_APPEND_JOB_ERROR
5132 append_item_to_jobs() failed, this happened because
5133 thread was killed while waiting for enqueue on worker.
5134 */
5135
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1649318 times.
1649319 if (exec_res >= SLAVE_APPLY_EVENT_AND_UPDATE_POS_UPDATE_POS_ERROR) {
5136
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 delete ev;
5137 #ifdef WITH_WSREP
5138
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 wsrep_after_statement(thd);
5139 #endif /* WITH_WSREP */
5140 1 return 1;
5141 }
5142
5143 #ifdef WITH_WSREP
5144
1/2
✓ Branch 0 taken 1649319 times.
✗ Branch 1 not taken.
1649318 mysql_mutex_lock(&thd->LOCK_wsrep_thd);
5145 1649319 enum wsrep::client_error wsrep_error = thd->wsrep_cs().current_error();
5146
1/2
✓ Branch 0 taken 1649319 times.
✗ Branch 1 not taken.
1649319 mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
5147
5148
1/2
✓ Branch 0 taken 1649319 times.
✗ Branch 1 not taken.
1649319 if (wsrep_error == wsrep::e_success) {
5149 #endif /* WITH_WSREP */
5150
5151
2/2
✓ Branch 0 taken 1553719 times.
✓ Branch 1 taken 95600 times.
1649319 if (slave_trans_retries) {
5152 1553719 int temp_err = 0;
5153 1553719 bool silent = false;
5154
1/2
✓ Branch 0 taken 105 times.
✗ Branch 1 not taken.
105 if (exec_res && !is_mts_worker(thd) /* no reexecution in MTS mode */ &&
5155
7/8
✓ Branch 0 taken 105 times.
✓ Branch 1 taken 1553614 times.
✓ Branch 2 taken 105 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 19 times.
✓ Branch 5 taken 86 times.
✓ Branch 6 taken 19 times.
✓ Branch 7 taken 1553700 times.
1553843 (temp_err = rli->has_temporary_error(thd, 0, &silent)) &&
5156
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 !thd->get_transaction()->cannot_safely_rollback(
5157 Transaction_ctx::SESSION)) {
5158 const char *errmsg;
5159 /*
5160 We were in a transaction which has been rolled back because of a
5161 temporary error;
5162 let's seek back to BEGIN log event and retry it all again.
5163 Note, if lock wait timeout (innodb_lock_wait_timeout exceeded)
5164 there is no rollback since 5.0.13 (ref: manual).
5165 We have to not only seek but also
5166 a) init_info(), to seek back to hot relay log's start for later
5167 (for when we will come back to this hot log after re-processing the
5168 possibly existing old logs where BEGIN is: applier_reader will
5169 then need the cache to be at position 0 (see comments at beginning
5170 of init_info()). b) init_relay_log_pos(), because the BEGIN may be
5171 an older relay log.
5172 */
5173
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 1 times.
19 if (rli->trans_retries < slave_trans_retries) {
5174 /*
5175 The transactions has to be rolled back before
5176 load_mi_and_rli_from_repositories is called. Because
5177 load_mi_and_rli_from_repositories will starts a new
5178 transaction if master_info_repository is TABLE.
5179 */
5180
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 rli->cleanup_context(thd, true);
5181 /*
5182 Temporary error status is both unneeded and harmful for following
5183 open-and-lock slave system tables but store its number first for
5184 monitoring purposes.
5185 */
5186 18 uint temp_trans_errno = thd->get_stmt_da()->mysql_errno();
5187
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 thd->clear_error();
5188
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 applier_reader->close();
5189 /*
5190 We need to figure out if there is a test case that covers
5191 this part. \Alfranio.
5192 */
5193
5194
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
18 if (load_mi_and_rli_from_repositories(rli->mi, false, SLAVE_SQL,
5195 false, true))
5196 LogErr(ERROR_LEVEL,
5197 ER_RPL_SLAVE_FAILED_TO_INIT_MASTER_INFO_STRUCTURE,
5198 rli->get_for_channel_str());
5199
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
18 else if (applier_reader->open(&errmsg))
5200 LogErr(ERROR_LEVEL, ER_RPL_SLAVE_CANT_INIT_RELAY_LOG_POSITION,
5201 rli->get_for_channel_str(), errmsg);
5202 else {
5203 18 exec_res = SLAVE_APPLY_EVENT_RETRY;
5204 /* chance for concurrent connection to get more locks */
5205 18 slave_sleep(thd,
5206
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 min<ulong>(rli->trans_retries, MAX_SLAVE_RETRY_PAUSE),
5207 sql_slave_killed, rli);
5208
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 mysql_mutex_lock(&rli->data_lock); // because of SHOW STATUS
5209
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 if (!silent) {
5210 18 rli->trans_retries++;
5211
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
18 if (rli->is_processing_trx()) {
5212
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
18 rli->retried_processing(temp_trans_errno,
5213 ER_THD_NONCONST(thd, temp_trans_errno),
5214 rli->trans_retries);
5215 }
5216 }
5217 18 rli->retried_trans++;
5218
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 mysql_mutex_unlock(&rli->data_lock);
5219 #ifndef NDEBUG
5220
4/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 14 times.
18 if (rli->trans_retries == 2 || rli->trans_retries == 6)
5221
4/6
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
4 DBUG_EXECUTE_IF("rpl_ps_tables_worker_retry", {
5222 rpl_replica_debug_point(DBUG_RPL_S_PS_TABLE_WORKER_RETRY);
5223 };);
5224
5225 #endif
5226
3/8
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 18 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
18 DBUG_PRINT("info", ("Slave retries transaction "
5227 "rli->trans_retries: %lu",
5228 rli->trans_retries));
5229 }
5230 } else {
5231 1 thd->fatal_error();
5232
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 rli->report(ERROR_LEVEL, thd->get_stmt_da()->mysql_errno(),
5233 "Slave SQL thread retried transaction %lu time(s) "
5234 "in vain, giving up. Consider raising the value of "
5235 "the replica_transaction_retries variable.",
5236 rli->trans_retries);
5237 }
5238
6/8
✓ Branch 0 taken 86 times.
✓ Branch 1 taken 1553614 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 86 times.
✓ Branch 4 taken 1553614 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 44310 times.
✓ Branch 7 taken 1509389 times.
3107313 } else if ((exec_res && !temp_err) ||
5239
2/2
✓ Branch 0 taken 44224 times.
✓ Branch 1 taken 1509389 times.
1553613 (opt_using_transactions &&
5240 1553614 rli->get_group_relay_log_pos() ==
5241 1553613 rli->get_event_relay_log_pos())) {
5242 /*
5243 Only reset the retry counter if the entire group succeeded
5244 or failed with a non-transient error. On a successful
5245 event, the execution will proceed as usual; in the case of a
5246 non-transient error, the slave will stop with an error.
5247 */
5248 44310 rli->trans_retries = 0; // restart from fresh
5249
3/8
✓ Branch 0 taken 44310 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 44310 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 44310 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
44310 DBUG_PRINT("info",
5250 ("Resetting retry counter, rli->trans_retries: %lu",
5251 rli->trans_retries));
5252 }
5253 }
5254 #ifdef WITH_WSREP
5255 }
5256 #endif /* WITH_WSREP */
5257
2/2
✓ Branch 0 taken 127 times.
✓ Branch 1 taken 1649191 times.
1649318 if (exec_res) {
5258
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 127 times.
127 delete ev;
5259 /* Raii object is explicitly updated 'cos this branch doesn't end func */
5260 127 rli->current_event = nullptr;
5261
3/4
✓ Branch 0 taken 1649191 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1253 times.
✓ Branch 3 taken 1647938 times.
1649191 } else if (rli->is_until_satisfied_after_dispatching_event()) {
5262
1/2
✓ Branch 0 taken 1253 times.
✗ Branch 1 not taken.
1253 mysql_mutex_lock(&rli->data_lock);
5263 1253 rli->abort_slave = true;
5264
1/2
✓ Branch 0 taken 1253 times.
✗ Branch 1 not taken.
1253 mysql_mutex_unlock(&rli->data_lock);
5265 #ifdef WITH_WSREP
5266
1/2
✓ Branch 0 taken 1253 times.
✗ Branch 1 not taken.
1253 wsrep_after_statement(thd);
5267 #endif /* WITH_WSREP */
5268 1253 return SLAVE_APPLY_EVENT_UNTIL_REACHED;
5269 }
5270 #ifdef WITH_WSREP
5271
1/2
✓ Branch 0 taken 1648066 times.
✗ Branch 1 not taken.
1648065 wsrep_after_statement(thd);
5272 #endif /* WITH_WSREP */
5273 1648066 return exec_res;
5274 }
5275
5276 /*
5277 It is impossible to read next event to finish the event group whenever a
5278 read event error happens. So MTS group status is set to MTS_KILLED_GROUP to
5279 force stop.
5280 */
5281
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (rli->mts_group_status == Relay_log_info::MTS_IN_GROUP)
5282 rli->mts_group_status = Relay_log_info::MTS_KILLED_GROUP;
5283
5284
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 mysql_mutex_unlock(&rli->data_lock);
5285
2/4
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
7 rli->report(ERROR_LEVEL, ER_SLAVE_RELAY_LOG_READ_FAILURE,
5286 ER_THD(thd, ER_SLAVE_RELAY_LOG_READ_FAILURE),
5287 "\
5288 Could not parse relay log event entry. The possible reasons are: the master's \
5289 binary log is corrupted (you can check this by running 'mysqlbinlog' on the \
5290 binary log), the slave's relay log is corrupted (you can check this by running \
5291 'mysqlbinlog' on the relay log), a network problem, the server was unable to \
5292 fetch a keyring key required to open an encrypted relay log file, or a bug in \
5293 the master's or slave's MySQL code. If you want to check the master's binary \
5294 log or slave's relay log, you will be able to know their names by issuing \
5295 'SHOW SLAVE STATUS' on this slave.\
5296 ");
5297 7 return SLAVE_APPLY_EVENT_AND_UPDATE_POS_APPLY_ERROR;
5298 1657520 }
5299
5300 1349793 static bool check_io_slave_killed(THD *thd, Master_info *mi, const char *info) {
5301
2/2
✓ Branch 0 taken 6354 times.
✓ Branch 1 taken 1343440 times.
1349793 if (io_slave_killed(thd, mi)) {
5302
2/2
✓ Branch 0 taken 6352 times.
✓ Branch 1 taken 2 times.
6354 if (info)
5303
8/16
✓ Branch 0 taken 6352 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6352 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6352 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 6352 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 6352 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 6352 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 6352 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 6352 times.
✗ Branch 15 not taken.
6352 LogErr(INFORMATION_LEVEL, ER_RPL_IO_THREAD_KILLED, info,
5304 mi->get_for_channel_str());
5305 6354 return true;
5306 }
5307 1343440 return false;
5308 }
5309
5310 /**
5311 @brief Try to reconnect slave IO thread.
5312
5313 @details Terminates current connection to master, sleeps for
5314 @c mi->connect_retry msecs and initiates new connection with
5315 @c safe_reconnect(). Variable pointed by @c retry_count is increased -
5316 if it exceeds @c mi->retry_count then connection is not re-established
5317 and function signals error.
5318
5319 Unless @c suppress_warnings is true, a warning is written to the
5320 server error log when reconnecting. The warning message, the
5321 messages used to report errors, and the thread stages, are taken
5322 from @c rm. In case @c mi->retry_count is exceeded, no messages are
5323 added to the log.
5324
5325 @param[in] thd Thread context.
5326 @param[in] mysql MySQL connection.
5327 @param[in] mi Master connection information.
5328 @param[in,out] retry_count Number of attempts to reconnect.
5329 @param[in] suppress_warnings true when a normal net read timeout
5330 has caused to reconnecting.
5331 @param[in] messages Error/warning messages and thread stage
5332 information. See class Reconnect_messages.
5333
5334 @retval 0 OK.
5335 @retval 1 There was an error.
5336 */
5337
5338 385 static int try_to_reconnect(THD *thd, MYSQL *mysql, Master_info *mi,
5339 uint *retry_count, bool suppress_warnings,
5340 const Reconnect_messages &messages) {
5341 385 mi->slave_running = MYSQL_SLAVE_RUN_NOT_CONNECT;
5342 385 THD_STAGE_INFO(thd, messages.stage_waiting_to_reconnect);
5343
4/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 379 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 6 times.
394 DBUG_EXECUTE_IF("hang_in_stage_replica_waiting_to_reconnect", {
5344 while (!io_slave_killed(thd, mi)) my_sleep(100000); // 0.1 second
5345 });
5346 385 thd->clear_active_vio();
5347 385 end_server(mysql);
5348
2/2
✓ Branch 0 taken 157 times.
✓ Branch 1 taken 228 times.
385 if ((*retry_count)++) {
5349
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 130 times.
157 if (*retry_count > mi->retry_count) return 1; // Don't retry forever
5350 130 slave_sleep(thd, mi->connect_retry, io_slave_killed, mi);
5351 }
5352
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 352 times.
358 if (check_io_slave_killed(thd, mi,
5353 messages.error_killed_while_waiting.c_str()))
5354 6 return 1;
5355 352 THD_STAGE_INFO(thd, messages.stage_reconnecting);
5356
4/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 346 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 6 times.
364 DBUG_EXECUTE_IF("hang_in_stage_replica_reconnecting", {
5357 while (!io_slave_killed(thd, mi)) my_sleep(100000); // 0.1 second
5358 });
5359
1/2
✓ Branch 0 taken 352 times.
✗ Branch 1 not taken.
352 if (!suppress_warnings) {
5360 char llbuff[22];
5361 /*
5362 Raise a warining during registering on master/requesting dump.
5363 Log a message reading event.
5364 */
5365
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 280 times.
352 if (messages.triggering_command.length()) {
5366 char buf[256];
5367
1/2
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
72 snprintf(buf, sizeof(buf), messages.triggering_error.c_str(),
5368 mi->get_io_rpl_log_name(),
5369 72 llstr(mi->get_master_log_pos(), llbuff));
5370
5371
2/4
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 72 times.
✗ Branch 3 not taken.
72 mi->report(WARNING_LEVEL, ER_SLAVE_MASTER_COM_FAILURE,
5372 ER_THD(thd, ER_SLAVE_MASTER_COM_FAILURE),
5373 messages.triggering_command.c_str(), buf);
5374 } else {
5375
10/20
✓ Branch 0 taken 280 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 280 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 280 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 280 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 280 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 280 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 280 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 280 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 280 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 280 times.
✗ Branch 19 not taken.
280 LogErr(INFORMATION_LEVEL, ER_SLAVE_RECONNECT_FAILED,
5376 mi->get_io_rpl_log_name(), llstr(mi->get_master_log_pos(), llbuff),
5377 mi->get_for_channel_str());
5378 }
5379 }
5380
8/14
✓ Branch 0 taken 352 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 296 times.
✓ Branch 3 taken 56 times.
✓ Branch 4 taken 296 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 296 times.
✓ Branch 8 taken 352 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 56 times.
✓ Branch 11 taken 296 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
352 if (safe_reconnect(thd, mysql, mi, true) || io_slave_killed(thd, mi)) {
5381
7/14
✓ Branch 0 taken 56 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 56 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 56 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 56 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 56 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 56 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 56 times.
✗ Branch 13 not taken.
56 LogErr(INFORMATION_LEVEL, ER_SLAVE_KILLED_AFTER_RECONNECT);
5382 56 return 1;
5383 }
5384 296 return 0;
5385 }
5386
5387 /**
5388 Slave IO thread entry point.
5389
5390 @param arg Pointer to Master_info struct that holds information for
5391 the IO thread.
5392
5393 @return Always 0.
5394 */
5395 7059 extern "C" void *handle_slave_io(void *arg) {
5396 7059 THD *thd{nullptr}; // needs to be first for thread_stack
5397 7059 bool thd_added{false};
5398 MYSQL *mysql;
5399 7059 Master_info *mi = (Master_info *)arg;
5400 7059 Relay_log_info *rli = mi->rli;
5401 char llbuff[22];
5402 uint retry_count;
5403 bool suppress_warnings;
5404 int ret;
5405 7059 Global_THD_manager *thd_manager = Global_THD_manager::get_instance();
5406 // needs to call my_thread_init(), otherwise we get a coredump in DBUG_ stuff
5407
1/2
✓ Branch 0 taken 7059 times.
✗ Branch 1 not taken.
7059 my_thread_init();
5408 {
5409
1/2
✓ Branch 0 taken 7059 times.
✗ Branch 1 not taken.
7059 DBUG_TRACE;
5410
5411
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7059 times.
7059 assert(mi->inited);
5412 7059 mysql = nullptr;
5413
5414
1/2
✓ Branch 0 taken 7059 times.
✗ Branch 1 not taken.
7059 mysql_mutex_lock(&mi->run_lock);
5415
5416 /* Inform waiting threads that slave has started */
5417 7059 mi->slave_run_id++;
5418
5419 #ifndef NDEBUG
5420 7059 mi->events_until_exit = disconnect_slave_event_count;
5421 #endif
5422
5423
2/4
✓ Branch 0 taken 7059 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7059 times.
✗ Branch 3 not taken.
7059 thd = new THD; // note that constructor of THD uses DBUG_ !
5424
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7059 times.
7059 THD_CHECK_SENTRY(thd);
5425 7059 mi->info_thd = thd;
5426
5427 #ifdef HAVE_PSI_THREAD_INTERFACE
5428 // save the instrumentation for IO thread in mi->info_thd
5429
1/2
✓ Branch 0 taken 7059 times.
✗ Branch 1 not taken.
7059 struct PSI_thread *psi = PSI_THREAD_CALL(get_thread)();
5430
1/2
✓ Branch 0 taken 7059 times.
✗ Branch 1 not taken.
7059 thd_set_psi(mi->info_thd, psi);
5431 #endif
5432
1/2
✓ Branch 0 taken 7059 times.
✗ Branch 1 not taken.
7059 mysql_thread_set_psi_THD(thd);
5433
5434 7059 thd->thread_stack = (char *)&thd; // remember where our stack is
5435
1/2
✓ Branch 0 taken 7059 times.
✗ Branch 1 not taken.
7059 mi->clear_error();
5436 7059 mi->slave_running = 1;
5437
3/4
✓ Branch 0 taken 7059 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 7053 times.
7059 if (init_replica_thread(thd, SLAVE_THD_IO)) {
5438
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 mysql_cond_broadcast(&mi->start_cond);
5439
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 mysql_mutex_unlock(&mi->run_lock);
5440
2/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
6 mi->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
5441 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
5442 "Failed during slave I/O thread initialization ");
5443 6 goto err;
5444 }
5445
5446
1/2
✓ Branch 0 taken 7053 times.
✗ Branch 1 not taken.
7053 thd_manager->add_thd(thd);
5447 7053 thd_added = true;
5448
5449 7053 mi->abort_slave = false;
5450
1/2
✓ Branch 0 taken 7053 times.
✗ Branch 1 not taken.
7053 mysql_mutex_unlock(&mi->run_lock);
5451
1/2
✓ Branch 0 taken 7053 times.
✗ Branch 1 not taken.
7053 mysql_cond_broadcast(&mi->start_cond);
5452
5453 7131 connect_init:
5454
3/10
✓ Branch 0 taken 7131 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7131 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 7131 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
7131 DBUG_PRINT("master_info",
5455 ("log_file_name: '%s' position: %s", mi->get_master_log_name(),
5456 llstr(mi->get_master_log_pos(), llbuff)));
5457
5458 /* This must be called before run any binlog_relay_io hooks */
5459 7131 RPL_MASTER_INFO = mi;
5460
5461
6/8
✓ Branch 0 taken 7131 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5417 times.
✓ Branch 3 taken 1714 times.
✓ Branch 4 taken 1714 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 12 times.
✓ Branch 7 taken 7119 times.
7131 if (RUN_HOOK(binlog_relay_io, thread_start, (thd, mi))) {
5462
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 mi->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
5463 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
5464 "Failed to run 'thread_start' hook");
5465 12 goto err;
5466 }
5467
5468 7119 retry_count = 0;
5469
2/4
✓ Branch 0 taken 7119 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7119 times.
7119 if (!(mi->mysql = mysql = mysql_init(nullptr))) {
5470 mi->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
5471 ER_THD(thd, ER_SLAVE_FATAL_ERROR), "error in mysql_init()");
5472 goto err;
5473 }
5474
5475
1/2
✓ Branch 0 taken 7119 times.
✗ Branch 1 not taken.
7119 THD_STAGE_INFO(thd, stage_connecting_to_source);
5476
5477
3/4
✓ Branch 0 taken 7119 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6923 times.
✓ Branch 3 taken 196 times.
7119 if (!safe_connect(thd, mysql, mi)) {
5478
10/20
✓ Branch 0 taken 6923 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6923 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6923 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 6923 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 6923 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 6923 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 6923 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 6923 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 6923 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 6923 times.
✗ Branch 19 not taken.
6923 LogErr(SYSTEM_LEVEL, ER_RPL_SLAVE_CONNECTED_TO_MASTER_REPLICATION_STARTED,
5479 mi->get_for_channel_str(), mi->get_user(), mi->host, mi->port,
5480 mi->get_io_rpl_log_name(),
5481 llstr(mi->get_master_log_pos(), llbuff));
5482 } else {
5483
9/18
✓ Branch 0 taken 196 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 196 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 196 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 196 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 196 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 196 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 196 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 196 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 196 times.
✗ Branch 17 not taken.
196 LogErr(INFORMATION_LEVEL, ER_RPL_SLAVE_IO_THREAD_KILLED,
5484 mi->get_for_channel_str());
5485 196 goto err;
5486 }
5487
5488 7219 connected:
5489
5490 /*
5491 When using auto positioning, the slave IO thread will always start reading
5492 a transaction from the beginning of the transaction (transaction's first
5493 event). So, we have to reset the transaction boundary parser after
5494 (re)connecting.
5495 If not using auto positioning, the Relay_log_info::rli_init_info() took
5496 care of putting the mi->transaction_parser in the correct state when
5497 initializing Received_gtid_set from relay log during slave server starts,
5498 as the IO thread might had stopped in the middle of a transaction.
5499 */
5500
2/2
✓ Branch 0 taken 2345 times.
✓ Branch 1 taken 4874 times.
7219 if (mi->is_auto_position()) {
5501
1/2
✓ Branch 0 taken 2345 times.
✗ Branch 1 not taken.
2345 mi->transaction_parser.reset();
5502
1/2
✓ Branch 0 taken 2345 times.
✗ Branch 1 not taken.
2345 mi->clear_queueing_trx(true /* need_lock*/);
5503 }
5504
5505 7219 mi->reset_network_error();
5506
5507
4/6
✓ Branch 0 taken 7219 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 7216 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
7219 DBUG_EXECUTE_IF("dbug.before_get_running_status_yes", {
5508 rpl_replica_debug_point(DBUG_RPL_S_BEFORE_RUNNING_STATUS, thd);
5509 };);
5510
3/4
✓ Branch 0 taken 7219 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 7217 times.
7219 DBUG_EXECUTE_IF("dbug.calculate_sbm_after_previous_gtid_log_event", {
5511 /* Fake that thread started 3 minutes ago */
5512 thd->start_time.tv_sec -= 180;
5513 };);
5514
3/4
✓ Branch 0 taken 7219 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 7216 times.
7219 DBUG_EXECUTE_IF("dbug.calculate_sbm_after_fake_rotate_log_event", {
5515 /* Fake that thread started 3 minutes ago */
5516 thd->start_time.tv_sec -= 180;
5517 };);
5518
1/2
✓ Branch 0 taken 7219 times.
✗ Branch 1 not taken.
7219 mysql_mutex_lock(&mi->run_lock);
5519 7219 mi->slave_running = MYSQL_SLAVE_RUN_CONNECT;
5520
1/2
✓ Branch 0 taken 7219 times.
✗ Branch 1 not taken.
7219 mysql_mutex_unlock(&mi->run_lock);
5521
5522
1/2
✓ Branch 0 taken 7219 times.
✗ Branch 1 not taken.
7219 THD_STAGE_INFO(thd, stage_checking_source_version);
5523
1/2
✓ Branch 0 taken 7219 times.
✗ Branch 1 not taken.
7219 ret = get_master_version_and_clock(mysql, mi);
5524
3/4
✓ Branch 0 taken 7156 times.
✓ Branch 1 taken 63 times.
✓ Branch 2 taken 7156 times.
✗ Branch 3 not taken.
7219 if (!ret) ret = get_master_uuid(mysql, mi);
5525
3/4
✓ Branch 0 taken 7154 times.
✓ Branch 1 taken 65 times.
✓ Branch 2 taken 7154 times.
✗ Branch 3 not taken.
7219 if (!ret) ret = io_thread_init_commands(mysql, mi);
5526
5527
6/6
✓ Branch 0 taken 7154 times.
✓ Branch 1 taken 65 times.
✓ Branch 2 taken 152 times.
✓ Branch 3 taken 7002 times.
✓ Branch 4 taken 152 times.
✓ Branch 5 taken 7067 times.
7219 if (!ret && mi->is_source_connection_auto_failover()) {
5528
1/2
✓ Branch 0 taken 152 times.
✗ Branch 1 not taken.
152 ret = Async_conn_failover_manager::get_source_quorum_status(mysql, mi);
5529 }
5530
5531
2/2
✓ Branch 0 taken 87 times.
✓ Branch 1 taken 7132 times.
7219 if (ret == 1) /* Fatal error */
5532 87 goto err;
5533
5534
7/8
✓ Branch 0 taken 7122 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 7122 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 7118 times.
✓ Branch 6 taken 14 times.
✓ Branch 7 taken 7118 times.
7132 if (ret == 2 || DBUG_EVALUATE_IF(
5535 "simulate_reconnect_after_failed_registration", 1, 0)) {
5536
3/4
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 12 times.
14 if (check_io_slave_killed(
5537 mi->info_thd, mi,
5538 "Slave I/O thread killed "
5539 "while calling get_master_version_and_clock(...)"))
5540 2 goto err;
5541 12 suppress_warnings = false;
5542 /* Try to reconnect because the error was caused by a transient network
5543 * problem */
5544
3/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 8 times.
12 if (try_to_reconnect(thd, mysql, mi, &retry_count, suppress_warnings,
5545 reconnect_messages_after_failed_registration))
5546 4 goto err;
5547 8 goto connected;
5548 }
5549
5550 /*
5551 Register ourselves with the master.
5552 */
5553
1/2
✓ Branch 0 taken 7118 times.
✗ Branch 1 not taken.
7118 THD_STAGE_INFO(thd, stage_registering_replica_on_source);
5554
3/4
✓ Branch 0 taken 7118 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 85 times.
✓ Branch 3 taken 7033 times.
7118 if (register_slave_on_master(mysql, mi, &suppress_warnings)) {
5555
3/4
✓ Branch 0 taken 85 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 84 times.
✓ Branch 3 taken 1 times.
85 if (!check_io_slave_killed(thd, mi,
5556 "Slave I/O thread killed "
5557 "while registering slave on master")) {
5558
8/16
✓ Branch 0 taken 84 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 84 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 84 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 84 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 84 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 84 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 84 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 84 times.
✗ Branch 15 not taken.
84 LogErr(ERROR_LEVEL, ER_RPL_SLAVE_IO_THREAD_CANT_REGISTER_ON_MASTER);
5559
3/4
✓ Branch 0 taken 84 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
✓ Branch 3 taken 60 times.
84 if (try_to_reconnect(thd, mysql, mi, &retry_count, suppress_warnings,
5560 reconnect_messages_after_failed_registration))
5561 24 goto err;
5562 } else
5563 1 goto err;
5564 60 goto connected;
5565 }
5566
5567
3/8
✓ Branch 0 taken 7033 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7033 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 7033 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
7033 DBUG_PRINT("info", ("Starting reading binary log from master"));
5568
3/4
✓ Branch 0 taken 7203 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7033 times.
✓ Branch 3 taken 170 times.
7203 while (!io_slave_killed(thd, mi)) {
5569 MYSQL_RPL rpl;
5570
5571
1/2
✓ Branch 0 taken 7033 times.
✗ Branch 1 not taken.
7033 THD_STAGE_INFO(thd, stage_requesting_binlog_dump);
5572
4/6
✓ Branch 0 taken 7033 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7033 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 7029 times.
14066 if (request_dump(thd, mysql, &rpl, mi, &suppress_warnings) ||
5573
3/4
✓ Branch 0 taken 7033 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 7029 times.
7033 DBUG_EVALUATE_IF("simulate_reconnect_after_failed_binlog_dump", 1,
5574 0)) {
5575
9/18
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 4 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 4 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 4 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 4 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 4 times.
✗ Branch 17 not taken.
4 LogErr(ERROR_LEVEL, ER_RPL_SLAVE_ERROR_REQUESTING_BINLOG_DUMP,
5576 mi->get_for_channel_str());
5577
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (check_io_slave_killed(thd, mi,
5578 "Slave I/O thread killed while "
5579
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
8 "requesting master dump") ||
5580
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 try_to_reconnect(thd, mysql, mi, &retry_count, suppress_warnings,
5581 reconnect_messages_after_failed_dump))
5582 6489 goto err;
5583 228 goto connected;
5584 }
5585 const char *event_buf;
5586
5587
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7029 times.
7029 assert(mi->last_error().number == 0);
5588
3/4
✓ Branch 0 taken 1349556 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1349386 times.
✓ Branch 3 taken 170 times.
1349556 while (!io_slave_killed(thd, mi)) {
5589 ulong event_len;
5590 /*
5591 We say "waiting" because read_event() will wait if there's nothing to
5592 read. But if there's something to read, it will not wait. The
5593 important thing is to not confuse users by saying "reading" whereas
5594 we're in fact receiving nothing.
5595 */
5596
1/2
✓ Branch 0 taken 1349385 times.
✗ Branch 1 not taken.
1349386 THD_STAGE_INFO(thd, stage_waiting_for_source_to_send_event);
5597
1/2
✓ Branch 0 taken 1349239 times.
✗ Branch 1 not taken.
1349385 event_len = read_event(mysql, &rpl, mi, &suppress_warnings);
5598
5599
9/14
✓ Branch 0 taken 1349239 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 1349234 times.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 4 times.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 times.
1349239 DBUG_EXECUTE_IF(
5600 "relay_xid_trigger", if (event_len != packet_error) {
5601 const uchar *event_buf2 =
5602 static_cast<const uchar *>(mysql->net.read_pos + 1);
5603 Log_event_type event_type =
5604 static_cast<Log_event_type>(event_buf2[EVENT_TYPE_OFFSET]);
5605 if (event_type == binary_log::XID_EVENT) {
5606 static constexpr char act[] =
5607 "now signal relay_xid_reached wait_for resume";
5608 assert(
5609 !debug_sync_set_action(current_thd, STRING_WITH_LEN(act)));
5610 }
5611 });
5612
5613
3/4
✓ Branch 0 taken 1349240 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6343 times.
✓ Branch 3 taken 1342897 times.
1349239 if (check_io_slave_killed(thd, mi,
5614 "Slave I/O thread killed while "
5615 "reading event"))
5616 6485 goto err;
5617
5618
4/4
✓ Branch 0 taken 1342567 times.
✓ Branch 1 taken 330 times.
✓ Branch 2 taken 334 times.
✓ Branch 3 taken 1342563 times.
2685464 if (event_len == packet_error ||
5619
3/4
✓ Branch 0 taken 1342567 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 1342563 times.
1342567 DBUG_EVALUATE_IF("simulate_reconnect_after_failed_event_read", 1,
5620 0)) {
5621
1/2
✓ Branch 0 taken 334 times.
✗ Branch 1 not taken.
334 uint mysql_error_number = mysql_errno(mysql);
5622
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 46 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 285 times.
334 switch (mysql_error_number) {
5623 3 case CR_NET_PACKET_TOO_LARGE:
5624
8/16
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 3 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 3 times.
✗ Branch 15 not taken.
3 LogErr(ERROR_LEVEL,
5625 ER_RPL_LOG_ENTRY_EXCEEDS_REPLICA_MAX_ALLOWED_PACKET,
5626 replica_max_allowed_packet);
5627
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 mi->report(ERROR_LEVEL, ER_SERVER_NET_PACKET_TOO_LARGE, "%s",
5628 "Got a packet bigger than "
5629 "'replica_max_allowed_packet' bytes");
5630 3 goto err;
5631 46 case ER_MASTER_FATAL_ERROR_READING_BINLOG:
5632
3/6
✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 46 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 46 times.
✗ Branch 5 not taken.
46 mi->report(ERROR_LEVEL,
5633 ER_SERVER_MASTER_FATAL_ERROR_READING_BINLOG,
5634 ER_THD(thd, ER_MASTER_FATAL_ERROR_READING_BINLOG),
5635 mysql_error_number, mysql_error(mysql));
5636 46 goto err;
5637 case ER_OUT_OF_RESOURCES:
5638 LogErr(ERROR_LEVEL, ER_RPL_SLAVE_STOPPING_AS_MASTER_OOM);
5639 mi->report(ERROR_LEVEL, ER_SERVER_OUT_OF_RESOURCES, "%s",
5640 ER_THD(thd, ER_SERVER_OUT_OF_RESOURCES));
5641 goto err;
5642 }
5643
3/4
✓ Branch 0 taken 285 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 57 times.
✓ Branch 3 taken 228 times.
285 if (try_to_reconnect(thd, mysql, mi, &retry_count, suppress_warnings,
5644 reconnect_messages_after_failed_event_read))
5645 57 goto err;
5646 228 goto connected;
5647 } // if (event_len == packet_error)
5648
5649 1342563 retry_count = 0; // ok event, reset retry counter
5650
1/2
✓ Branch 0 taken 1342563 times.
✗ Branch 1 not taken.
1342563 THD_STAGE_INFO(thd, stage_queueing_source_event_to_the_relay_log);
5651 1342563 event_buf = (const char *)mysql->net.read_pos + 1;
5652
3/10
✓ Branch 0 taken 1342563 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1342563 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1342563 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
1342563 DBUG_PRINT("info", ("IO thread received event of type %s",
5653 Log_event::get_type_str(
5654 (Log_event_type)event_buf[EVENT_TYPE_OFFSET])));
5655
5/8
✓ Branch 0 taken 1342563 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 970492 times.
✓ Branch 3 taken 372071 times.
✓ Branch 4 taken 372071 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1342563 times.
1342563 if (RUN_HOOK(binlog_relay_io, after_read_event,
5656 (thd, mi, (const char *)mysql->net.read_pos + 1, event_len,
5657 &event_buf, &event_len))) {
5658 mi->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
5659 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
5660 "Failed to run 'after_read_event' hook");
5661 goto err;
5662 }
5663
5664 /* XXX: 'synced' should be updated by queue_event to indicate
5665 whether event has been synced to disk */
5666 1342563 bool synced = false;
5667 #ifndef NDEBUG
5668 1342563 bool was_in_trx = false;
5669
3/4
✓ Branch 0 taken 1342563 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1025226 times.
✓ Branch 3 taken 317337 times.
1342563 if (mi->is_queueing_trx()) {
5670 1025226 was_in_trx = true;
5671
4/6
✓ Branch 0 taken 1025226 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 1025216 times.
✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
1025226 DBUG_EXECUTE_IF("rpl_ps_tables_queue", {
5672 rpl_replica_debug_point(DBUG_RPL_S_PS_TABLE_QUEUE);
5673 };);
5674 }
5675 #endif
5676
1/2
✓ Branch 0 taken 1342563 times.
✗ Branch 1 not taken.
1342563 QUEUE_EVENT_RESULT queue_res = queue_event(mi, event_buf, event_len);
5677
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 1342530 times.
1342563 if (queue_res == QUEUE_EVENT_ERROR_QUEUING) {
5678
2/4
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 33 times.
✗ Branch 3 not taken.
33 mi->report(ERROR_LEVEL, ER_SLAVE_RELAY_LOG_WRITE_FAILURE,
5679 ER_THD(thd, ER_SLAVE_RELAY_LOG_WRITE_FAILURE),
5680 "could not queue event from master");
5681 33 goto err;
5682 }
5683 #ifndef NDEBUG
5684
7/8
✓ Branch 0 taken 1025219 times.
✓ Branch 1 taken 317311 times.
✓ Branch 2 taken 1025219 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 264860 times.
✓ Branch 5 taken 760359 times.
✓ Branch 6 taken 264860 times.
✓ Branch 7 taken 1077670 times.
1342530 if (was_in_trx && !mi->is_queueing_trx()) {
5685
4/6
✓ Branch 0 taken 264860 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 264850 times.
✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
264860 DBUG_EXECUTE_IF("rpl_ps_tables",
5686 { rpl_replica_debug_point(DBUG_RPL_S_PS_TABLES); };);
5687 }
5688 #endif
5689
5/8
✓ Branch 0 taken 1342530 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 970459 times.
✓ Branch 3 taken 372071 times.
✓ Branch 4 taken 372071 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1342530 times.
1342530 if (RUN_HOOK(binlog_relay_io, after_queue_event,
5690 (thd, mi, event_buf, event_len, synced))) {
5691 mi->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
5692 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
5693 "Failed to run 'after_queue_event' hook");
5694 goto err;
5695 }
5696
5697 /* The event was queued, but there was a failure flushing master info */
5698
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1342530 times.
1342530 if (queue_res == QUEUE_EVENT_ERROR_FLUSHING_INFO) {
5699 mi->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
5700 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
5701 "Failed to flush master info.");
5702 goto err;
5703 }
5704
5705
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1342530 times.
1342530 assert(queue_res == QUEUE_EVENT_OK);
5706 /*
5707 Pause the IO thread execution and wait for
5708 'continue_after_queue_event' signal to continue IO thread
5709 execution.
5710 */
5711
4/6
✓ Branch 0 taken 1342530 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 93 times.
✓ Branch 3 taken 1342437 times.
✓ Branch 4 taken 93 times.
✗ Branch 5 not taken.
1342530 DBUG_EXECUTE_IF("pause_after_queue_event", {
5712 rpl_replica_debug_point(DBUG_RPL_S_PAUSE_AFTER_QUEUE_EV);
5713 };);
5714
5715 /*
5716 See if the relay logs take too much space.
5717 We don't lock mi->rli->log_space_lock here; this dirty read saves time
5718 and does not introduce any problem:
5719 - if mi->rli->ignore_log_space_limit is 1 but becomes 0 just after (so
5720 the clean value is 0), then we are reading only one more event as we
5721 should, and we'll block only at the next event. No big deal.
5722 - if mi->rli->ignore_log_space_limit is 0 but becomes 1 just after (so
5723 the clean value is 1), then we are going into
5724 wait_for_relay_log_space() for no reason, but this function will do a
5725 clean read, notice the clean value and exit immediately.
5726 */
5727 #ifndef NDEBUG
5728 {
5729 char llbuf1[22], llbuf2[22];
5730
3/12
✓ Branch 0 taken 1342530 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1342530 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1342530 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
1342530 DBUG_PRINT("info", ("log_space_limit=%s log_space_total=%s "
5731 "ignore_log_space_limit=%d",
5732 llstr(rli->log_space_limit, llbuf1),
5733 llstr(rli->log_space_total, llbuf2),
5734 (int)rli->ignore_log_space_limit));
5735 }
5736 #endif
5737
5738
3/4
✓ Branch 0 taken 1342530 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 1342517 times.
1342530 DBUG_EXECUTE_IF("rpl_set_relay_log_limits", {
5739 rli->log_space_limit = 10;
5740 rli->log_space_total = 20;
5741 };);
5742
5743 2685213 if (rli->log_space_limit &&
5744
6/6
✓ Branch 0 taken 153 times.
✓ Branch 1 taken 1342377 times.
✓ Branch 2 taken 109 times.
✓ Branch 3 taken 44 times.
✓ Branch 4 taken 73 times.
✓ Branch 5 taken 1342457 times.
1342639 rli->log_space_limit < rli->log_space_total &&
5745
2/2
✓ Branch 0 taken 73 times.
✓ Branch 1 taken 36 times.
109 !rli->ignore_log_space_limit)
5746
3/4
✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 70 times.
73 if (wait_for_relay_log_space(rli)) {
5747
8/16
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 3 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 3 times.
✗ Branch 15 not taken.
3 LogErr(ERROR_LEVEL,
5748 ER_RPL_SLAVE_IO_THREAD_ABORTED_WAITING_FOR_RELAY_LOG_SPACE);
5749 3 goto err;
5750 }
5751
6/8
✓ Branch 0 taken 1342527 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 64 times.
✓ Branch 3 taken 1342463 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 62 times.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
1342527 DBUG_EXECUTE_IF("flush_after_reading_user_var_event", {
5752 if (event_buf[EVENT_TYPE_OFFSET] == binary_log::USER_VAR_EVENT)
5753 rpl_replica_debug_point(DBUG_RPL_S_FLUSH_AFTER_USERV_EV);
5754 });
5755
5/6
✓ Branch 0 taken 1342527 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 25 times.
✓ Branch 3 taken 1342502 times.
✓ Branch 4 taken 22 times.
✓ Branch 5 taken 3 times.
1342527 DBUG_EXECUTE_IF(
5756 "stop_io_after_reading_gtid_log_event",
5757 if (event_buf[EVENT_TYPE_OFFSET] == binary_log::GTID_LOG_EVENT)
5758 thd->killed = THD::KILLED_NO_VALUE;);
5759
5/6
✓ Branch 0 taken 1342527 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 50 times.
✓ Branch 3 taken 1342477 times.
✓ Branch 4 taken 23 times.
✓ Branch 5 taken 27 times.
1342527 DBUG_EXECUTE_IF(
5760 "stop_io_after_reading_query_log_event",
5761 if (event_buf[EVENT_TYPE_OFFSET] == binary_log::QUERY_EVENT)
5762 thd->killed = THD::KILLED_NO_VALUE;);
5763
5/6
✓ Branch 0 taken 1342527 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 57 times.
✓ Branch 3 taken 1342470 times.
✓ Branch 4 taken 11 times.
✓ Branch 5 taken 46 times.
1342527 DBUG_EXECUTE_IF(
5764 "stop_io_after_reading_user_var_log_event",
5765 if (event_buf[EVENT_TYPE_OFFSET] == binary_log::USER_VAR_EVENT)
5766 thd->killed = THD::KILLED_NO_VALUE;);
5767
5/6
✓ Branch 0 taken 1342526 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 33 times.
✓ Branch 3 taken 1342493 times.
✓ Branch 4 taken 11 times.
✓ Branch 5 taken 22 times.
1342527 DBUG_EXECUTE_IF(
5768 "stop_io_after_reading_table_map_event",
5769 if (event_buf[EVENT_TYPE_OFFSET] == binary_log::TABLE_MAP_EVENT)
5770 thd->killed = THD::KILLED_NO_VALUE;);
5771
5/6
✓ Branch 0 taken 1342526 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 71 times.
✓ Branch 3 taken 1342455 times.
✓ Branch 4 taken 11 times.
✓ Branch 5 taken 60 times.
1342526 DBUG_EXECUTE_IF(
5772 "stop_io_after_reading_xid_log_event",
5773 if (event_buf[EVENT_TYPE_OFFSET] == binary_log::XID_EVENT)
5774 thd->killed = THD::KILLED_NO_VALUE;);
5775
5/6
✓ Branch 0 taken 1342526 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 23 times.
✓ Branch 3 taken 1342503 times.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 19 times.
1342526 DBUG_EXECUTE_IF(
5776 "stop_io_after_reading_write_rows_log_event",
5777 if (event_buf[EVENT_TYPE_OFFSET] == binary_log::WRITE_ROWS_EVENT)
5778 thd->killed = THD::KILLED_NO_VALUE;);
5779
5/6
✓ Branch 0 taken 1342526 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 1342519 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 6 times.
1342526 DBUG_EXECUTE_IF(
5780 "stop_io_after_reading_unknown_event",
5781 /*
5782 * Cast to uchar, because of Percona's events
5783 * which have values > 128. This causes ENUM_END_EVENT to be > 128
5784 * but event_buf is char, so comparison does not work.
5785 */
5786 if (static_cast<uchar>(event_buf[EVENT_TYPE_OFFSET]) >=
5787 binary_log::ENUM_END_EVENT) thd->killed =
5788 THD::KILLED_NO_VALUE;);
5789
3/4
✓ Branch 0 taken 1342526 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 1342513 times.
1342526 DBUG_EXECUTE_IF("stop_io_after_queuing_event",
5790 thd->killed = THD::KILLED_NO_VALUE;);
5791 /*
5792 After event is flushed to relay log file, memory used
5793 by thread's mem_root is not required any more.
5794 Hence adding ClearorReuse() to do the
5795 cleanup, otherwise a long running IO thread can
5796 cause OOM error.
5797 */
5798
1/2
✓ Branch 0 taken 1342527 times.
✗ Branch 1 not taken.
1342526 thd->mem_root->ClearForReuse();
5799 }
5800 }
5801
5802 // error = 0;
5803 170 err:
5804 /*
5805 If source_connection_auto_failover (async connection failover) is
5806 enabled, this server is not a Group Replication SECONDARY and
5807 Replica IO thread is not killed but failed due to network error, a
5808 connection to another source is attempted.
5809 */
5810 6991 if (mi->is_source_connection_auto_failover() &&
5811
7/8
✓ Branch 0 taken 185 times.
✓ Branch 1 taken 6806 times.
✓ Branch 2 taken 185 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 183 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 100 times.
✓ Branch 7 taken 6891 times.
7174 !is_group_replication_member_secondary() &&
5812
3/4
✓ Branch 0 taken 183 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 83 times.
✓ Branch 3 taken 100 times.
183 (!io_slave_killed(thd, mi) ||
5813
2/6
✓ Branch 0 taken 83 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 83 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
83 (!io_slave_killed(thd, mi) && mi->is_network_error()))) {
5814
4/6
✓ Branch 0 taken 100 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 97 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
100 DBUG_EXECUTE_IF("async_conn_failover_crash", DBUG_SUICIDE(););
5815
5816 /*
5817 Get the sender to connect to.
5818 If there is a STOP REPLICA ongoing for any channel, that is, a
5819 channel_map lock cannot be acquired by this channel IO thread,
5820 then this channel IO thread does skip the next sender selection.
5821 */
5822 Async_conn_failover_manager::enum_do_auto_conn_failover_error
5823 97 update_source_error =
5824 Async_conn_failover_manager::ACF_RETRIABLE_ERROR;
5825
2/4
✓ Branch 0 taken 97 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 97 times.
✗ Branch 3 not taken.
97 if (!channel_map.tryrdlock()) {
5826 update_source_error =
5827
1/2
✓ Branch 0 taken 97 times.
✗ Branch 1 not taken.
97 Async_conn_failover_manager::do_auto_conn_failover(mi, false);
5828
1/2
✓ Branch 0 taken 97 times.
✗ Branch 1 not taken.
97 channel_map.unlock();
5829 }
5830
5/8
✓ Branch 0 taken 97 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 79 times.
✓ Branch 4 taken 18 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 18 times.
✗ Branch 7 not taken.
97 DBUG_EXECUTE_IF("replica_retry_count_exceed", {
5831 if (Async_conn_failover_manager::ACF_NO_ERROR == update_source_error) {
5832 rpl_replica_debug_point(DBUG_RPL_S_RETRY_COUNT_EXCEED, thd);
5833 }
5834 });
5835
5836
2/2
✓ Branch 0 taken 91 times.
✓ Branch 1 taken 6 times.
97 if (Async_conn_failover_manager::ACF_NO_SOURCES_ERROR !=
5837 update_source_error) {
5838 /* Wait before reconnect to avoid resources starvation. */
5839
1/2
✓ Branch 0 taken 91 times.
✗ Branch 1 not taken.
91 my_sleep(1000000);
5840
5841 /* After waiting, recheck that a STOP REPLICA did not happen. */
5842
3/4
✓ Branch 0 taken 91 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 78 times.
✓ Branch 3 taken 13 times.
91 if (!io_slave_killed(thd, mi)) {
5843 /* Reconnect. */
5844
2/2
✓ Branch 0 taken 77 times.
✓ Branch 1 taken 1 times.
78 if (mysql) {
5845
1/2
✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
77 thd->clear_active_vio();
5846
1/2
✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
77 mysql_close(mysql);
5847 77 mi->mysql = nullptr;
5848 }
5849 78 goto connect_init;
5850 }
5851 }
5852 }
5853
5854 // print the current replication position
5855
10/20
✓ Branch 0 taken 6910 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6910 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6910 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 6910 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 6910 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 6910 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 6910 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 6910 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 6910 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 6910 times.
✗ Branch 19 not taken.
6910 LogErr(INFORMATION_LEVEL, ER_RPL_SLAVE_IO_THREAD_EXITING,
5856 mi->get_for_channel_str(), mi->get_io_rpl_log_name(),
5857 llstr(mi->get_master_log_pos(), llbuff));
5858 /* At this point the I/O thread will not try to reconnect anymore. */
5859 6910 mi->atomic_is_stopping = true;
5860
4/6
✓ Branch 0 taken 6910 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1682 times.
✓ Branch 3 taken 5228 times.
✓ Branch 4 taken 1682 times.
✗ Branch 5 not taken.
6910 (void)RUN_HOOK(binlog_relay_io, thread_stop, (thd, mi));
5861 /*
5862 Pause the IO thread and wait for 'continue_to_stop_io_thread'
5863 signal to continue to shutdown the IO thread.
5864 */
5865
2/6
✓ Branch 0 taken 6910 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6910 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
6910 DBUG_EXECUTE_IF("pause_after_io_thread_stop_hook", {
5866 rpl_replica_debug_point(DBUG_RPL_S_PAUSE_AFTER_IO_STOP, thd);
5867 };);
5868
5869
1/2
✓ Branch 0 taken 6910 times.
✗ Branch 1 not taken.
6910 thd->reset_query();
5870
1/2
✓ Branch 0 taken 6910 times.
✗ Branch 1 not taken.
6910 thd->reset_db(NULL_CSTR);
5871
2/2
✓ Branch 0 taken 6893 times.
✓ Branch 1 taken 17 times.
6910 if (mysql) {
5872 /*
5873 Here we need to clear the active VIO before closing the
5874 connection with the master. The reason is that THD::awake()
5875 might be called from terminate_slave_thread() because somebody
5876 issued a STOP SLAVE. If that happends, the shutdown_active_vio()
5877 can be called in the middle of closing the VIO associated with
5878 the 'mysql' object, causing a crash.
5879 */
5880
1/2
✓ Branch 0 taken 6893 times.
✗ Branch 1 not taken.
6893 thd->clear_active_vio();
5881
1/2
✓ Branch 0 taken 6893 times.
✗ Branch 1 not taken.
6893 mysql_close(mysql);
5882 6893 mi->mysql = nullptr;
5883 }
5884
1/2
✓ Branch 0 taken 6910 times.
✗ Branch 1 not taken.
6910 write_ignored_events_info_to_relay_log(thd, mi);
5885
1/2
✓ Branch 0 taken 6910 times.
✗ Branch 1 not taken.
6910 THD_STAGE_INFO(thd, stage_waiting_for_replica_mutex_on_exit);
5886
1/2
✓ Branch 0 taken 6910 times.
✗ Branch 1 not taken.
6910 mysql_mutex_lock(&mi->run_lock);
5887 /*
5888 Clean information used to start slave in order to avoid
5889 security issues.
5890 */
5891
1/2
✓ Branch 0 taken 6910 times.
✗ Branch 1 not taken.
6910 mi->reset_start_info();
5892 /* Forget the relay log's format */
5893
1/2
✓ Branch 0 taken 6910 times.
✗ Branch 1 not taken.
6910 mysql_mutex_lock(rli->relay_log.get_log_lock());
5894
1/2
✓ Branch 0 taken 6910 times.
✗ Branch 1 not taken.
6910 mi->set_mi_description_event(nullptr);
5895
1/2
✓ Branch 0 taken 6910 times.
✗ Branch 1 not taken.
6910 mysql_mutex_unlock(rli->relay_log.get_log_lock());
5896
5897 // destructor will not free it, because net.vio is 0
5898
2/4
✓ Branch 0 taken 6910 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6910 times.
✗ Branch 3 not taken.
6910 thd->get_protocol_classic()->end_net();
5899
5900
1/2
✓ Branch 0 taken 6910 times.
✗ Branch 1 not taken.
6910 thd->release_resources();
5901
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6910 times.
6910 THD_CHECK_SENTRY(thd);
5902
3/4
✓ Branch 0 taken 6904 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 6904 times.
✗ Branch 3 not taken.
6910 if (thd_added) thd_manager->remove_thd(thd);
5903
5904 6910 mi->abort_slave = false;
5905 6910 mi->slave_running = 0;
5906 6910 mi->atomic_is_stopping = false;
5907
1/2
✓ Branch 0 taken 6910 times.
✗ Branch 1 not taken.
6910 mysql_mutex_lock(&mi->info_thd_lock);
5908 6910 mi->info_thd = nullptr;
5909
1/2
✓ Branch 0 taken 6910 times.
✗ Branch 1 not taken.
6910 mysql_mutex_unlock(&mi->info_thd_lock);
5910
5911 /*
5912 The thd can only be destructed after indirect references
5913 through mi->info_thd are cleared: mi->info_thd= NULL.
5914
5915 For instance, user thread might be issuing show_slave_status
5916 and attempting to read mi->info_thd->proc_info().
5917 Therefore thd must only be deleted after info_thd is set
5918 to NULL.
5919 */
5920
1/2
✓ Branch 0 taken 6910 times.
✗ Branch 1 not taken.
6910 mysql_thread_set_psi_THD(nullptr);
5921
1/2
✓ Branch 0 taken 6910 times.
✗ Branch 1 not taken.
6910 delete thd;
5922
5923 /*
5924 Note: the order of the two following calls (first broadcast, then unlock)
5925 is important. Otherwise a killer_thread can execute between the calls and
5926 delete the mi structure leading to a crash! (see BUG#25306 for details)
5927 */
5928
1/2
✓ Branch 0 taken 6910 times.
✗ Branch 1 not taken.
6910 mysql_cond_broadcast(&mi->stop_cond); // tell the world we are done
5929
4/6
✓ Branch 0 taken 6910 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 6907 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
6910 DBUG_EXECUTE_IF("simulate_replica_delay_at_terminate_bug38694", sleep(5););
5930
1/2
✓ Branch 0 taken 6910 times.
✗ Branch 1 not taken.
6910 mysql_mutex_unlock(&mi->run_lock);
5931 6910 }
5932
1/2
✓ Branch 0 taken 6910 times.
✗ Branch 1 not taken.
6910 my_thread_end();
5933 #if OPENSSL_VERSION_NUMBER < 0x10100000L
5934 ERR_remove_thread_state(0);
5935 #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
5936 6910 my_thread_exit(nullptr);
5937 return (nullptr); // Avoid compiler warnings
5938 }
5939
5940 /*
5941 Check the temporary directory used by commands like
5942 LOAD DATA INFILE.
5943 */
5944 10030 static int check_temp_dir(char *tmp_file, const char *channel_name) {
5945 int fd;
5946 MY_DIR *dirp;
5947 char tmp_dir[FN_REFLEN];
5948 size_t tmp_dir_size;
5949
5950
1/2
✓ Branch 0 taken 10030 times.
✗ Branch 1 not taken.
10030 DBUG_TRACE;
5951
5952 /*
5953 Get the directory from the temporary file.
5954 */
5955
1/2
✓ Branch 0 taken 10030 times.
✗ Branch 1 not taken.
10030 dirname_part(tmp_dir, tmp_file, &tmp_dir_size);
5956
5957 /*
5958 Check if the directory exists.
5959 */
5960
3/4
✓ Branch 0 taken 10030 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 10027 times.
10030 if (!(dirp = my_dir(tmp_dir, MYF(MY_WME)))) return 1;
5961
1/2
✓ Branch 0 taken 10027 times.
✗ Branch 1 not taken.
10027 my_dirend(dirp);
5962
5963 /*
5964 Check permissions to create a file.
5965 */
5966 // append the server UUID to the temp file name.
5967 10027 constexpr uint size_of_tmp_file_name = 768;
5968 static_assert(size_of_tmp_file_name >= FN_REFLEN + TEMP_FILE_MAX_LEN, "");
5969
1/2
✓ Branch 0 taken 10027 times.
✗ Branch 1 not taken.
10027 char *unique_tmp_file_name = (char *)my_malloc(
5970 key_memory_rpl_replica_check_temp_dir, size_of_tmp_file_name, MYF(0));
5971 /*
5972 In the case of Multisource replication, the file create
5973 sometimes fail because of there is a race that a second SQL
5974 thread might create the same file and the creation fails.
5975 TO overcome this, we add a channel name to get a unique file name.
5976 */
5977
5978 /* @TODO: dangerous. Prevent this buffer flow */
5979 10027 snprintf(unique_tmp_file_name, size_of_tmp_file_name, "%s%s%s", tmp_file,
5980 channel_name, server_uuid);
5981
1/2
✓ Branch 0 taken 10027 times.
✗ Branch 1 not taken.
10027 if ((fd = mysql_file_create(key_file_misc, unique_tmp_file_name, CREATE_MODE,
5982
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10027 times.
10027 O_WRONLY | O_EXCL | O_NOFOLLOW, MYF(MY_WME))) < 0)
5983 return 1;
5984
5985 /*
5986 Clean up.
5987 */
5988
1/2
✓ Branch 0 taken 10027 times.
✗ Branch 1 not taken.
10027 mysql_file_close(fd, MYF(0));
5989
5990
1/2
✓ Branch 0 taken 10027 times.
✗ Branch 1 not taken.
10027 mysql_file_delete(key_file_misc, unique_tmp_file_name, MYF(0));
5991
1/2
✓ Branch 0 taken 10027 times.
✗ Branch 1 not taken.
10027 my_free(unique_tmp_file_name);
5992 10027 return 0;
5993 10030 }
5994
5995 /*
5996 Worker thread for the parallel execution of the replication events.
5997 */
5998 extern "C" {
5999 39763 static void *handle_slave_worker(void *arg) {
6000 THD *thd; /* needs to be first for thread_stack */
6001 39763 bool thd_added = false;
6002 39763 int error = 0;
6003 39763 Slave_worker *w = (Slave_worker *)arg;
6004 39763 Relay_log_info *rli = w->c_rli;
6005 39763 ulong purge_cnt = 0;
6006 39763 ulonglong purge_size = 0;
6007 39763 struct slave_job_item _item, *job_item = &_item;
6008 39763 Global_THD_manager *thd_manager = Global_THD_manager::get_instance();
6009 #ifdef HAVE_PSI_THREAD_INTERFACE
6010 struct PSI_thread *psi;
6011 #endif
6012
6013
1/2
✓ Branch 0 taken 39763 times.
✗ Branch 1 not taken.
39763 my_thread_init();
6014
1/2
✓ Branch 0 taken 39763 times.
✗ Branch 1 not taken.
39763 DBUG_TRACE;
6015
6016
2/4
✓ Branch 0 taken 39763 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 39763 times.
✗ Branch 3 not taken.
39763 thd = new THD;
6017
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39763 times.
39763 if (!thd) {
6018 LogErr(ERROR_LEVEL, ER_RPL_SLAVE_CANT_INITIALIZE_SLAVE_WORKER,
6019 rli->get_for_channel_str());
6020 goto err;
6021 }
6022
1/2
✓ Branch 0 taken 39763 times.
✗ Branch 1 not taken.
39763 mysql_mutex_lock(&w->info_thd_lock);
6023 39763 w->info_thd = thd;
6024
1/2
✓ Branch 0 taken 39763 times.
✗ Branch 1 not taken.
39763 mysql_mutex_unlock(&w->info_thd_lock);
6025 39763 thd->thread_stack = (char *)&thd;
6026
6027 #ifdef HAVE_PSI_THREAD_INTERFACE
6028 // save the instrumentation for worker thread in w->info_thd
6029
1/2
✓ Branch 0 taken 39763 times.
✗ Branch 1 not taken.
39763 psi = PSI_THREAD_CALL(get_thread)();
6030
1/2
✓ Branch 0 taken 39763 times.
✗ Branch 1 not taken.
39763 thd_set_psi(w->info_thd, psi);
6031 #endif
6032
1/2
✓ Branch 0 taken 39763 times.
✗ Branch 1 not taken.
39763 mysql_thread_set_psi_THD(thd);
6033
6034
2/4
✓ Branch 0 taken 39763 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 39763 times.
39763 if (init_replica_thread(thd, SLAVE_THD_WORKER)) {
6035 // todo make SQL thread killed
6036 LogErr(ERROR_LEVEL, ER_RPL_SLAVE_CANT_INITIALIZE_SLAVE_WORKER,
6037 rli->get_for_channel_str());
6038 goto err;
6039 }
6040 39763 thd->rli_slave = w;
6041
1/2
✓ Branch 0 taken 39763 times.
✗ Branch 1 not taken.
39763 thd->init_query_mem_roots();
6042
6043
3/4
✓ Branch 0 taken 39763 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14596 times.
✓ Branch 3 taken 25167 times.
39763 if (channel_map.is_group_replication_channel_name(rli->get_channel())) {
6044
3/4
✓ Branch 0 taken 14596 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9251 times.
✓ Branch 3 taken 5345 times.
14596 if (channel_map.is_group_replication_channel_name(rli->get_channel(),
6045 true)) {
6046 9251 thd->rpl_thd_ctx.set_rpl_channel_type(GR_APPLIER_CHANNEL);
6047 } else {
6048 5345 thd->rpl_thd_ctx.set_rpl_channel_type(GR_RECOVERY_CHANNEL);
6049 }
6050 } else {
6051 25167 thd->rpl_thd_ctx.set_rpl_channel_type(RPL_STANDARD_CHANNEL);
6052 }
6053
6054 39763 w->set_filter(rli->rpl_filter);
6055
6056
3/4
✓ Branch 0 taken 39763 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 736 times.
✓ Branch 3 taken 39027 times.
39763 if ((w->deferred_events_collecting = w->rpl_filter->is_on()))
6057
2/4
✓ Branch 0 taken 736 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 736 times.
✗ Branch 3 not taken.
736 w->deferred_events = new Deferred_log_events();
6058
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39763 times.
39763 assert(thd->rli_slave->info_thd == thd);
6059
6060 /* Set applier thread InnoDB priority */
6061
1/2
✓ Branch 0 taken 39763 times.
✗ Branch 1 not taken.
39763 set_thd_tx_priority(thd, rli->get_thd_tx_priority());
6062 /* Set write set related options */
6063
1/2
✓ Branch 0 taken 39763 times.
✗ Branch 1 not taken.
39763 set_thd_write_set_options(thd, rli->get_ignore_write_set_memory_limit(),
6064 39763 rli->get_allow_drop_write_set());
6065
6066
1/2
✓ Branch 0 taken 39763 times.
✗ Branch 1 not taken.
39763 thd->variables.require_row_format = rli->is_row_format_required();
6067
6068 39763 if (Relay_log_info::PK_CHECK_STREAM !=
6069
3/4
✓ Branch 0 taken 39763 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 68 times.
✓ Branch 3 taken 39695 times.
39763 rli->get_require_table_primary_key_check())
6070 68 thd->variables.sql_require_primary_key =
6071
1/2
✓ Branch 0 taken 68 times.
✗ Branch 1 not taken.
68 (rli->get_require_table_primary_key_check() ==
6072 Relay_log_info::PK_CHECK_ON);
6073
2/4
✓ Branch 0 taken 39763 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 39763 times.
✗ Branch 3 not taken.
39763 w->set_require_table_primary_key_check(
6074 rli->get_require_table_primary_key_check());
6075
6076 // Replicas shall not create GIPKs if source tables have no PKs
6077 39763 thd->variables.sql_generate_invisible_primary_key = false;
6078
6079
1/2
✓ Branch 0 taken 39763 times.
✗ Branch 1 not taken.
39763 thd_manager->add_thd(thd);
6080 39763 thd_added = true;
6081
6082 #ifdef WITH_WSREP
6083
1/2
✓ Branch 0 taken 39763 times.
✗ Branch 1 not taken.
39763 wsrep_open(thd);
6084
2/4
✓ Branch 0 taken 39763 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 39763 times.
39763 if (wsrep_before_command(thd)) {
6085 WSREP_WARN("Slave SQL worker wsrep_before_command() failed");
6086 goto err;
6087 }
6088 #endif /* WITH_WSREP */
6089
6090
2/4
✓ Branch 0 taken 39763 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 39763 times.
39763 if (w->update_is_transactional()) {
6091 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
6092 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
6093 "Error checking if the worker repository is transactional.");
6094 goto err;
6095 }
6096
6097
2/2
✓ Branch 0 taken 39201 times.
✓ Branch 1 taken 562 times.
39763 if (rli->get_commit_order_manager() != nullptr)
6098
1/2
✓ Branch 0 taken 39201 times.
✗ Branch 1 not taken.
39201 rli->get_commit_order_manager()->init_worker_context(
6099 *w); // Initialize worker context within Commit_order_manager
6100
6101
1/2
✓ Branch 0 taken 39763 times.
✗ Branch 1 not taken.
39763 mysql_mutex_lock(&w->jobs_lock);
6102 39763 w->running_status = Slave_worker::RUNNING;
6103
1/2
✓ Branch 0 taken 39763 times.
✗ Branch 1 not taken.
39763 mysql_cond_signal(&w->jobs_cond);
6104
6105
1/2
✓ Branch 0 taken 39763 times.
✗ Branch 1 not taken.
39763 mysql_mutex_unlock(&w->jobs_lock);
6106
6107
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39763 times.
39763 assert(thd->is_slave_error == 0);
6108
6109 39763 w->stats_exec_time = w->stats_read_time = 0;
6110
1/2
✓ Branch 0 taken 39763 times.
✗ Branch 1 not taken.
39763 set_timespec_nsec(&w->ts_exec[0], 0);
6111
1/2
✓ Branch 0 taken 39763 times.
✗ Branch 1 not taken.
39763 set_timespec_nsec(&w->ts_exec[1], 0);
6112
1/2
✓ Branch 0 taken 39763 times.
✗ Branch 1 not taken.
39763 set_timespec_nsec(&w->stats_begin, 0);
6113
6114 // No need to report anything, all error handling will be performed in the
6115 // slave SQL thread.
6116
4/6
✓ Branch 0 taken 39763 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 39763 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 39759 times.
✓ Branch 5 taken 4 times.
39763 if (!rli->check_privilege_checks_user())
6117
1/2
✓ Branch 0 taken 39759 times.
✗ Branch 1 not taken.
39759 rli->initialize_security_context(w->info_thd); // Worker security context
6118 // initialization with
6119 // `PRIVILEGE_CHECKS_USER`
6120
6121
2/2
✓ Branch 0 taken 319985 times.
✓ Branch 1 taken 38111 times.
358096 while (!error) {
6122
1/2
✓ Branch 0 taken 318333 times.
✗ Branch 1 not taken.
319985 error = slave_worker_exec_job_group(w, rli);
6123 }
6124
6125 /*
6126 Cleanup after an error requires clear_error() go first.
6127 Otherwise assert(!all) in binlog_rollback()
6128 */
6129
1/2
✓ Branch 0 taken 38145 times.
✗ Branch 1 not taken.
38111 thd->clear_error();
6130
1/2
✓ Branch 0 taken 37920 times.
✗ Branch 1 not taken.
38145 w->cleanup_context(thd, error);
6131
6132
1/2
✓ Branch 0 taken 37642 times.
✗ Branch 1 not taken.
37920 mysql_mutex_lock(&w->jobs_lock);
6133
6134
3/4
✓ Branch 0 taken 38805 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1740 times.
✓ Branch 3 taken 37065 times.
39382 while (w->jobs.de_queue(job_item)) {
6135 1740 purge_cnt++;
6136 1740 purge_size += job_item->data->common_header->data_written;
6137
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1740 times.
1740 assert(job_item->data);
6138
1/2
✓ Branch 0 taken 1740 times.
✗ Branch 1 not taken.
1740 delete job_item->data;
6139 }
6140
6141
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37358 times.
37065 assert(w->jobs.get_length() == 0);
6142
6143
1/2
✓ Branch 0 taken 38266 times.
✗ Branch 1 not taken.
37358 mysql_mutex_unlock(&w->jobs_lock);
6144
6145
1/2
✓ Branch 0 taken 38335 times.
✗ Branch 1 not taken.
38266 mysql_mutex_lock(&rli->pending_jobs_lock);
6146 38335 rli->pending_jobs -= purge_cnt;
6147 38335 rli->mts_pending_jobs_size -= purge_size;
6148
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38335 times.
38335 assert(rli->mts_pending_jobs_size < rli->mts_pending_jobs_size_max);
6149
6150
1/2
✓ Branch 0 taken 38334 times.
✗ Branch 1 not taken.
38335 mysql_mutex_unlock(&rli->pending_jobs_lock);
6151
6152 /*
6153 In MTS case cleanup_after_session() has be called explicitly.
6154 TODO: to make worker thd be deleted before Slave_worker instance.
6155 */
6156
1/2
✓ Branch 0 taken 38334 times.
✗ Branch 1 not taken.
38334 if (thd->rli_slave) {
6157 38334 w->cleanup_after_session();
6158 38318 thd->rli_slave = nullptr;
6159 }
6160
1/2
✓ Branch 0 taken 38245 times.
✗ Branch 1 not taken.
38318 mysql_mutex_lock(&w->jobs_lock);
6161
6162 struct timespec stats_end;
6163
1/2
✓ Branch 0 taken 38260 times.
✗ Branch 1 not taken.
38245 set_timespec_nsec(&stats_end, 0);
6164
3/8
✓ Branch 0 taken 38064 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 38068 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 38068 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
38260 DBUG_PRINT("info",
6165 ("Worker %lu statistics: "
6166 "events processed = %lu "
6167 "online time = %llu "
6168 "events exec time = %llu "
6169 "events read time = %llu "
6170 "hungry waits = %lu "
6171 "priv queue overfills = %llu ",
6172 w->id, w->events_done, diff_timespec(&stats_end, &w->stats_begin),
6173 w->stats_exec_time, w->stats_read_time, w->wq_empty_waits,
6174 w->jobs.waited_overfill));
6175
6176 38068 w->running_status = Slave_worker::NOT_RUNNING;
6177
6178
1/2
✓ Branch 0 taken 38078 times.
✗ Branch 1 not taken.
38068 mysql_mutex_lock(&w->info_thd_lock);
6179 /* We will delete the THD descriptior in next step.
6180 Before Slave_worker is deleted in slave_stop_workers() its value will be
6181 copied by copy_values_for_PFS including info_thd member.
6182 The member is used in table_replication_applier_status_by_worker::make_row()
6183 however only if Slave_worker::running status is Slave_worker::RUNNING, so we
6184 are safe here.
6185 Without setting below member to nullptr, we would copy stale pointer anyway,
6186 so it is safer to explicitly say that
6187 */
6188 38078 w->info_thd = nullptr;
6189
1/2
✓ Branch 0 taken 38289 times.
✗ Branch 1 not taken.
38078 mysql_mutex_unlock(&w->info_thd_lock);
6190
6191
1/2
✓ Branch 0 taken 38120 times.
✗ Branch 1 not taken.
38289 mysql_cond_signal(&w->jobs_cond); // famous last goodbye
6192
6193
1/2
✓ Branch 0 taken 38305 times.
✗ Branch 1 not taken.
38120 mysql_mutex_unlock(&w->jobs_lock);
6194
6195 38305 err:
6196
6197 #ifdef WITH_WSREP
6198
1/2
✓ Branch 0 taken 37998 times.
✗ Branch 1 not taken.
38305 wsrep_after_command_before_result(thd);
6199
1/2
✓ Branch 0 taken 38103 times.
✗ Branch 1 not taken.
37998 wsrep_after_command_after_result(thd);
6200
1/2
✓ Branch 0 taken 38159 times.
✗ Branch 1 not taken.
38103 wsrep_close(thd);
6201 #endif /* WITH_WSREP */
6202
6203
2/2
✓ Branch 0 taken 38153 times.
✓ Branch 1 taken 6 times.
38159 if (thd) {
6204 /*
6205 The slave code is very bad. Notice that it is missing
6206 several clean up calls here. I've just added what was
6207 necessary to avoid valgrind errors.
6208
6209 /Alfranio
6210 */
6211
2/4
✓ Branch 0 taken 37770 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 37996 times.
✗ Branch 3 not taken.
38153 thd->get_protocol_classic()->end_net();
6212
6213 /*
6214 to avoid close_temporary_tables() closing temp tables as those
6215 are Coordinator's burden.
6216 */
6217 37996 thd->system_thread = NON_SYSTEM_THREAD;
6218
1/2
✓ Branch 0 taken 38324 times.
✗ Branch 1 not taken.
37996 thd->release_resources();
6219
6220
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38324 times.
38324 THD_CHECK_SENTRY(thd);
6221
3/4
✓ Branch 0 taken 38323 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 38318 times.
✗ Branch 3 not taken.
38324 if (thd_added) thd_manager->remove_thd(thd);
6222
1/2
✓ Branch 0 taken 38149 times.
✗ Branch 1 not taken.
38319 mysql_thread_set_psi_THD(nullptr);
6223
1/2
✓ Branch 0 taken 38151 times.
✗ Branch 1 not taken.
38149 delete thd;
6224 }
6225
6226
1/2
✓ Branch 0 taken 38327 times.
✗ Branch 1 not taken.
37857 my_thread_end();
6227 #if OPENSSL_VERSION_NUMBER < 0x10100000L
6228 ERR_remove_thread_state(0);
6229 #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
6230 38327 my_thread_exit(nullptr);
6231 return nullptr;
6232 37528 }
6233 } // extern "C"
6234
6235 /**
6236 Orders jobs by comparing relay log information.
6237 */
6238
6239 20108 int mts_event_coord_cmp(LOG_POS_COORD *id1, LOG_POS_COORD *id2) {
6240 20108 longlong filecmp = strcmp(id1->file_name, id2->file_name);
6241 20108 longlong poscmp = id1->pos - id2->pos;
6242 return (filecmp < 0
6243
2/2
✓ Branch 0 taken 4125 times.
✓ Branch 1 taken 15983 times.
24233 ? -1
6244
5/6
✓ Branch 0 taken 4125 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3289 times.
✓ Branch 3 taken 836 times.
✓ Branch 4 taken 242 times.
✓ Branch 5 taken 3047 times.
24233 : (filecmp > 0 ? 1 : (poscmp < 0 ? -1 : (poscmp > 0 ? 1 : 0))));
6245 }
6246
6247 6991 bool mts_recovery_groups(Relay_log_info *rli) {
6248 6991 Log_event *ev = nullptr;
6249 6991 bool is_error = false;
6250 6991 bool flag_group_seen_begin = false;
6251 6991 uint recovery_group_cnt = 0;
6252 6991 bool not_reached_commit = true;
6253
6254 // Value-initialization, to avoid compiler warnings on push_back.
6255 6991 Slave_job_group job_worker = Slave_job_group();
6256
6257 6991 LOG_INFO linfo;
6258 6991 my_off_t offset = 0;
6259 6991 MY_BITMAP *groups = &rli->recovery_groups;
6260
1/2
✓ Branch 0 taken 6991 times.
✗ Branch 1 not taken.
6991 THD *thd = current_thd;
6261
6262
1/2
✓ Branch 0 taken 6991 times.
✗ Branch 1 not taken.
6991 DBUG_TRACE;
6263
6264
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6991 times.
6991 assert(rli->replica_parallel_workers == 0);
6265
6266 /*
6267 Although mts_recovery_groups() is reentrant it returns
6268 early if the previous invocation raised any bit in
6269 recovery_groups bitmap.
6270 */
6271
2/2
✓ Branch 0 taken 153 times.
✓ Branch 1 taken 6838 times.
6991 if (rli->is_mts_recovery()) return false;
6272
6273 /*
6274 The process of relay log recovery for the multi threaded applier
6275 is focused on marking transactions as already executed so they are
6276 skipped when the SQL thread applies them.
6277 This is important as the position stored for the last executed relay log
6278 position may be behind what transactions workers already handled.
6279 When GTID_MODE=ON however we can use the old relay log position, even if
6280 stale as applied transactions will be skipped due to GTIDs auto skip
6281 feature.
6282 */
6283
8/10
✓ Branch 0 taken 6838 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1977 times.
✓ Branch 3 taken 4861 times.
✓ Branch 4 taken 1977 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1764 times.
✓ Branch 7 taken 213 times.
✓ Branch 8 taken 1764 times.
✓ Branch 9 taken 5074 times.
8815 if (global_gtid_mode.get() == Gtid_mode::ON && rli->mi &&
6284 1977 rli->mi->is_auto_position()) {
6285 1764 rli->mts_recovery_group_cnt = 0;
6286 1764 return false;
6287 }
6288
6289 /*
6290 Save relay log position to compare with worker's position.
6291 */
6292 5074 LOG_POS_COORD cp = {const_cast<char *>(rli->get_group_master_log_name()),
6293 5074 rli->get_group_master_log_pos()};
6294
6295 /*
6296 Gathers information on valuable workers and stores it in
6297 above_lwm_jobs in asc ordered by the master binlog coordinates.
6298 */
6299 5074 Prealloced_array<Slave_job_group, 16> above_lwm_jobs(PSI_NOT_INSTRUMENTED);
6300
1/2
✓ Branch 0 taken 5074 times.
✗ Branch 1 not taken.
5074 above_lwm_jobs.reserve(rli->recovery_parallel_workers);
6301
6302 /*
6303 When info tables are used and autocommit= 0 we force a new
6304 transaction start to avoid table access deadlocks when START SLAVE
6305 is executed after STOP SLAVE with MTS enabled.
6306 */
6307
3/4
✓ Branch 0 taken 5074 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 5073 times.
5074 if (is_autocommit_off_and_infotables(thd))
6308
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (trans_begin(thd)) goto err;
6309
6310
2/2
✓ Branch 0 taken 19776 times.
✓ Branch 1 taken 5073 times.
24849 for (uint id = 0; id < rli->recovery_parallel_workers; id++) {
6311 Slave_worker *worker =
6312
1/2
✓ Branch 0 taken 19776 times.
✗ Branch 1 not taken.
19776 Rpl_info_factory::create_worker(opt_rli_repository_id, id, rli, true);
6313
6314
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 19775 times.
19776 if (!worker) {
6315
2/6
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
1 if (is_autocommit_off_and_infotables(thd)) trans_rollback(thd);
6316 1 goto err;
6317 }
6318
6319 LOG_POS_COORD w_last = {
6320 19775 const_cast<char *>(worker->get_group_master_log_name()),
6321 19775 worker->get_group_master_log_pos()};
6322
2/2
✓ Branch 0 taken 242 times.
✓ Branch 1 taken 19533 times.
19775 if (mts_event_coord_cmp(&w_last, &cp) > 0) {
6323 /*
6324 Inserts information into a dynamic array for further processing.
6325 The jobs/workers are ordered by the last checkpoint positions
6326 workers have seen.
6327 */
6328 242 job_worker.worker = worker;
6329 242 job_worker.checkpoint_log_pos = worker->checkpoint_master_log_pos;
6330 242 job_worker.checkpoint_log_name = worker->checkpoint_master_log_name;
6331
6332
1/2
✓ Branch 0 taken 242 times.
✗ Branch 1 not taken.
242 above_lwm_jobs.push_back(job_worker);
6333 } else {
6334 /*
6335 Deletes the worker because its jobs are included in the latest
6336 checkpoint.
6337 */
6338
1/2
✓ Branch 0 taken 19533 times.
✗ Branch 1 not taken.
19533 delete worker;
6339 }
6340 }
6341
6342 /*
6343 When info tables are used and autocommit= 0 we force transaction
6344 commit to avoid table access deadlocks when START SLAVE is executed
6345 after STOP SLAVE with MTS enabled.
6346 */
6347
3/4
✓ Branch 0 taken 5073 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 5072 times.
5073 if (is_autocommit_off_and_infotables(thd))
6348
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (trans_commit(thd)) goto err;
6349
6350 /*
6351 In what follows, the group Recovery Bitmap is constructed.
6352
6353 seek(lwm);
6354
6355 while(w= next(above_lwm_w))
6356 do
6357 read G
6358 if G == w->last_comm
6359 w.B << group_cnt++;
6360 RB |= w.B;
6361 break;
6362 else
6363 group_cnt++;
6364 while(!eof);
6365 continue;
6366 */
6367
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5073 times.
5073 assert(!rli->recovery_groups_inited);
6368
6369
3/4
✓ Branch 0 taken 5073 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 226 times.
✓ Branch 3 taken 4847 times.
5073 if (!above_lwm_jobs.empty()) {
6370
1/2
✓ Branch 0 taken 226 times.
✗ Branch 1 not taken.
226 bitmap_init(groups, nullptr, MTS_MAX_BITS_IN_GROUP);
6371 226 rli->recovery_groups_inited = true;
6372 226 bitmap_clear_all(groups);
6373 }
6374 5073 rli->mts_recovery_group_cnt = 0;
6375
4/6
✓ Branch 0 taken 5073 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5315 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 242 times.
✓ Branch 5 taken 5073 times.
5315 for (Slave_job_group *jg = above_lwm_jobs.begin(); jg != above_lwm_jobs.end();
6376 ++jg) {
6377 242 Slave_worker *w = jg->worker;
6378 242 LOG_POS_COORD w_last = {const_cast<char *>(w->get_group_master_log_name()),
6379 242 w->get_group_master_log_pos()};
6380
6381
8/16
✓ Branch 0 taken 242 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 242 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 242 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 242 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 242 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 242 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 242 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 242 times.
✗ Branch 15 not taken.
242 LogErr(INFORMATION_LEVEL,
6382 ER_RPL_MTS_GROUP_RECOVERY_RELAY_LOG_INFO_FOR_WORKER, w->id,
6383 w->get_group_relay_log_name(), w->get_group_relay_log_pos(),
6384 w->get_group_master_log_name(), w->get_group_master_log_pos());
6385
6386 242 recovery_group_cnt = 0;
6387 242 not_reached_commit = true;
6388
2/4
✓ Branch 0 taken 242 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 242 times.
242 if (rli->relay_log.find_log_pos(&linfo, rli->get_group_relay_log_name(),
6389 true)) {
6390 LogErr(ERROR_LEVEL, ER_RPL_ERROR_LOOKING_FOR_LOG,
6391 rli->get_group_relay_log_name());
6392 goto err;
6393 }
6394 242 offset = rli->get_group_relay_log_pos();
6395
6396
1/2
✓ Branch 0 taken 242 times.
✗ Branch 1 not taken.
242 Relaylog_file_reader relaylog_file_reader(opt_replica_sql_verify_checksum);
6397
6398
2/2
✓ Branch 0 taken 272 times.
✓ Branch 1 taken 242 times.
514 for (int checking = 0; not_reached_commit; checking++) {
6399
2/4
✓ Branch 0 taken 272 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 272 times.
272 if (relaylog_file_reader.open(linfo.log_file_name, offset)) {
6400 LogErr(ERROR_LEVEL, ER_BINLOG_FILE_OPEN_FAILED,
6401 relaylog_file_reader.get_error_str());
6402 goto err;
6403 }
6404
6405
4/4
✓ Branch 0 taken 1533 times.
✓ Branch 1 taken 242 times.
✓ Branch 2 taken 1503 times.
✓ Branch 3 taken 272 times.
3308 while (not_reached_commit &&
6406
3/4
✓ Branch 0 taken 1533 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1503 times.
✓ Branch 3 taken 30 times.
1533 (ev = relaylog_file_reader.read_event_object())) {
6407
2/4
✓ Branch 0 taken 1503 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1503 times.
1503 assert(ev->is_valid());
6408
6409
2/2
✓ Branch 0 taken 1413 times.
✓ Branch 1 taken 60 times.
2976 if (ev->get_type_code() == binary_log::ROTATE_EVENT ||
6410
2/2
✓ Branch 0 taken 1383 times.
✓ Branch 1 taken 30 times.
2886 ev->get_type_code() == binary_log::FORMAT_DESCRIPTION_EVENT ||
6411
5/6
✓ Branch 0 taken 1473 times.
✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1383 times.
✓ Branch 4 taken 120 times.
✓ Branch 5 taken 1383 times.
4389 ev->get_type_code() == binary_log::PREVIOUS_GTIDS_LOG_EVENT ||
6412 1383 ev->get_type_code() == binary_log::START_5_7_ENCRYPTION_EVENT) {
6413
1/2
✓ Branch 0 taken 120 times.
✗ Branch 1 not taken.
120 delete ev;
6414 120 ev = nullptr;
6415 120 continue;
6416 }
6417
6418
3/8
✓ Branch 0 taken 1383 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1383 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1383 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
1383 DBUG_PRINT("mts", ("Event Recoverying relay log info "
6419 "group_mster_log_name %s, event_master_log_pos "
6420 "%llu type code %u.",
6421 linfo.log_file_name, ev->common_header->log_pos,
6422 ev->get_type_code()));
6423
6424
3/4
✓ Branch 0 taken 1383 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 214 times.
✓ Branch 3 taken 1169 times.
1383 if (ev->starts_group()) {
6425 214 flag_group_seen_begin = true;
6426
7/8
✓ Branch 0 taken 1169 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 952 times.
✓ Branch 3 taken 217 times.
✓ Branch 4 taken 446 times.
✓ Branch 5 taken 506 times.
✓ Branch 6 taken 333 times.
✓ Branch 7 taken 836 times.
1832 } else if ((ev->ends_group() || !flag_group_seen_begin) &&
6427
2/2
✓ Branch 0 taken 333 times.
✓ Branch 1 taken 330 times.
663 !is_gtid_event(ev)) {
6428 333 int ret = 0;
6429 LOG_POS_COORD ev_coord = {
6430 333 const_cast<char *>(rli->get_group_master_log_name()),
6431 333 ev->common_header->log_pos};
6432 333 flag_group_seen_begin = false;
6433 333 recovery_group_cnt++;
6434
6435
8/16
✓ Branch 0 taken 333 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 333 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 333 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 333 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 333 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 333 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 333 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 333 times.
✗ Branch 15 not taken.
333 LogErr(INFORMATION_LEVEL, ER_RPL_MTS_GROUP_RECOVERY_RELAY_LOG_INFO,
6436 rli->get_group_master_log_name_info(),
6437 ev->common_header->log_pos);
6438
2/2
✓ Branch 0 taken 242 times.
✓ Branch 1 taken 91 times.
333 if ((ret = mts_event_coord_cmp(&ev_coord, &w_last)) == 0) {
6439 #ifndef NDEBUG
6440
2/2
✓ Branch 0 taken 339 times.
✓ Branch 1 taken 242 times.
581 for (uint i = 0; i <= w->worker_checkpoint_seqno; i++) {
6441
2/2
✓ Branch 0 taken 270 times.
✓ Branch 1 taken 69 times.
339 if (bitmap_is_set(&w->group_executed, i))
6442
3/8
✓ Branch 0 taken 270 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 270 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 270 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
270 DBUG_PRINT("mts", ("Bit %u is set.", i));
6443 else
6444
3/8
✓ Branch 0 taken 69 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 69 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 69 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
69 DBUG_PRINT("mts", ("Bit %u is not set.", i));
6445 }
6446 #endif
6447
3/8
✓ Branch 0 taken 242 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 242 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 242 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
242 DBUG_PRINT("mts",
6448 ("Doing a shift ini(%lu) end(%lu).",
6449 (w->worker_checkpoint_seqno + 1) - recovery_group_cnt,
6450 w->worker_checkpoint_seqno));
6451
6452 242 for (uint i = (w->worker_checkpoint_seqno + 1) - recovery_group_cnt,
6453 242 j = 0;
6454
2/2
✓ Branch 0 taken 333 times.
✓ Branch 1 taken 242 times.
575 i <= w->worker_checkpoint_seqno; i++, j++) {
6455
2/2
✓ Branch 0 taken 270 times.
✓ Branch 1 taken 63 times.
333 if (bitmap_is_set(&w->group_executed, i)) {
6456
3/8
✓ Branch 0 taken 270 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 270 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 270 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
270 DBUG_PRINT("mts", ("Setting bit %u.", j));
6457
1/2
✓ Branch 0 taken 270 times.
✗ Branch 1 not taken.
270 bitmap_test_and_set(groups, j);
6458 }
6459 }
6460 242 not_reached_commit = false;
6461 } else
6462
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 91 times.
91 assert(ret < 0);
6463 }
6464
1/2
✓ Branch 0 taken 1383 times.
✗ Branch 1 not taken.
1383 delete ev;
6465 1383 ev = nullptr;
6466 }
6467
6468
1/2
✓ Branch 0 taken 272 times.
✗ Branch 1 not taken.
272 relaylog_file_reader.close();
6469 272 offset = BIN_LOG_HEADER_SIZE;
6470
5/8
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 242 times.
✓ Branch 2 taken 30 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 30 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 272 times.
272 if (not_reached_commit && rli->relay_log.find_next_log(&linfo, true)) {
6471 LogErr(ERROR_LEVEL, ER_RPL_CANT_FIND_FOLLOWUP_FILE,
6472 linfo.log_file_name);
6473 goto err;
6474 }
6475 }
6476
6477 242 rli->mts_recovery_group_cnt =
6478 242 (rli->mts_recovery_group_cnt < recovery_group_cnt
6479 242 ? recovery_group_cnt
6480 : rli->mts_recovery_group_cnt);
6481
1/2
✓ Branch 0 taken 242 times.
✗ Branch 1 not taken.
242 }
6482
6483
3/4
✓ Branch 0 taken 226 times.
✓ Branch 1 taken 4847 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 226 times.
5073 assert(!rli->recovery_groups_inited ||
6484 rli->mts_recovery_group_cnt <= groups->n_bits);
6485
6486 5073 goto end;
6487 1 err:
6488 1 is_error = true;
6489 5074 end:
6490
6491
4/6
✓ Branch 0 taken 5074 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5316 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 242 times.
✓ Branch 5 taken 5074 times.
5316 for (Slave_job_group *jg = above_lwm_jobs.begin(); jg != above_lwm_jobs.end();
6492 ++jg) {
6493
1/2
✓ Branch 0 taken 242 times.
✗ Branch 1 not taken.
242 delete jg->worker;
6494 }
6495
6496
3/4
✓ Branch 0 taken 4848 times.
✓ Branch 1 taken 226 times.
✓ Branch 2 taken 4848 times.
✗ Branch 3 not taken.
5074 if (rli->mts_recovery_group_cnt == 0) rli->clear_mts_recovery_groups();
6497
6498 5074 return is_error;
6499 6991 }
6500
6501 425431 bool mta_checkpoint_routine(Relay_log_info *rli, bool force) {
6502 ulong cnt;
6503 425431 bool error = false;
6504 425431 time_t ts = 0;
6505
6506
1/2
✓ Branch 0 taken 425431 times.
✗ Branch 1 not taken.
425431 DBUG_TRACE;
6507
6508 #ifndef NDEBUG
6509
2/4
✓ Branch 0 taken 425431 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 425431 times.
425431 if (DBUG_EVALUATE_IF("check_replica_debug_group", 1, 0)) {
6510 if (!rli->gaq->count_done(rli)) return false;
6511 }
6512
4/6
✓ Branch 0 taken 425431 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 425415 times.
✓ Branch 4 taken 16 times.
✗ Branch 5 not taken.
425431 DBUG_EXECUTE_IF("mta_checkpoint", {
6513 rpl_replica_debug_point(DBUG_RPL_S_MTS_CHECKPOINT_START, rli->info_thd);
6514 };);
6515 #endif
6516
6517 #ifndef NDEBUG
6518 /*
6519 rli->checkpoint_group can have two possible values due to
6520 two possible status of the last (being scheduled) group.
6521 */
6522 const bool precondition =
6523
2/4
✓ Branch 0 taken 425431 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 425431 times.
425431 !rli->gaq->full() ||
6524 ((rli->rli_checkpoint_seqno == rli->checkpoint_group - 1 &&
6525 (rli->mts_group_status == Relay_log_info::MTS_IN_GROUP ||
6526 rli->mts_group_status == Relay_log_info::MTS_KILLED_GROUP)) ||
6527 rli->rli_checkpoint_seqno == rli->checkpoint_group);
6528
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 425431 times.
425431 if (!precondition) {
6529 fprintf(stderr, "rli->gaq->full() = %d\n", rli->gaq->full());
6530 fprintf(stderr, "rli->rl_checkpoint_seqno = %u\n",
6531 rli->rli_checkpoint_seqno);
6532 fprintf(stderr, "rli->checkpoint_group = %u\n", rli->checkpoint_group);
6533 fprintf(stderr, "rli->mts_group_status = %d\n", rli->mts_group_status);
6534 assert(precondition);
6535 }
6536 #endif
6537
6538 do {
6539
4/6
✓ Branch 0 taken 9842978 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9842432 times.
✓ Branch 3 taken 546 times.
✓ Branch 4 taken 9842426 times.
✗ Branch 5 not taken.
9842976 if (!is_mts_db_partitioned(rli)) mysql_mutex_lock(&rli->mts_gaq_LOCK);
6540
6541
1/2
✓ Branch 0 taken 9842971 times.
✗ Branch 1 not taken.
9842972 cnt = rli->gaq->move_queue_head(&rli->workers);
6542
6543
4/6
✓ Branch 0 taken 9842971 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9842425 times.
✓ Branch 3 taken 546 times.
✓ Branch 4 taken 9842425 times.
✗ Branch 5 not taken.
9842971 if (!is_mts_db_partitioned(rli)) mysql_mutex_unlock(&rli->mts_gaq_LOCK);
6544 #ifndef NDEBUG
6545
3/6
✓ Branch 0 taken 9842970 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9842970 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 9842970 times.
9842971 if (DBUG_EVALUATE_IF("check_replica_debug_group", 1, 0) &&
6546 cnt != opt_mta_checkpoint_period)
6547 LogErr(ERROR_LEVEL, ER_RPL_MTS_CHECKPOINT_PERIOD_DIFFERS_FROM_CNT);
6548 #endif
6549
5/6
✓ Branch 0 taken 9842968 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9698004 times.
✓ Branch 3 taken 86989 times.
✓ Branch 4 taken 9417736 times.
✓ Branch 5 taken 280268 times.
19627963 } while (!sql_slave_killed(rli->info_thd, rli) && cnt == 0 && force &&
6550
6/8
✓ Branch 0 taken 9784993 times.
✓ Branch 1 taken 57975 times.
✓ Branch 2 taken 9417734 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9417734 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 9417545 times.
✓ Branch 7 taken 425233 times.
29045507 !DBUG_EVALUATE_IF("check_replica_debug_group", 1, 0) &&
6551
1/2
✓ Branch 0 taken 9417546 times.
✗ Branch 1 not taken.
9417734 (my_sleep(rli->mts_coordinator_basic_nap), 1));
6552 /*
6553 This checks how many consecutive jobs where processed.
6554 If this value is different than zero the checkpoint
6555 routine can proceed. Otherwise, there is nothing to be
6556 done.
6557 */
6558
2/2
✓ Branch 0 taken 336747 times.
✓ Branch 1 taken 88486 times.
425233 if (cnt == 0) goto end;
6559
6560 /*
6561 The workers have completed cnt jobs from the gaq. This means that we
6562 should increment C->jobs_done by cnt.
6563 */
6564
6/8
✓ Branch 0 taken 88486 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 88486 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 88368 times.
✓ Branch 5 taken 118 times.
✓ Branch 6 taken 88368 times.
✓ Branch 7 taken 118 times.
88486 if (!is_mts_worker(rli->info_thd) && !is_mts_db_partitioned(rli)) {
6565
3/8
✓ Branch 0 taken 88368 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 88368 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 88368 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
88368 DBUG_PRINT("info", ("jobs_done this itr=%ld", cnt));
6566 88368 static_cast<Mts_submode_logical_clock *>(rli->current_mts_submode)
6567 88368 ->jobs_done += cnt;
6568 }
6569
6570
1/2
✓ Branch 0 taken 88486 times.
✗ Branch 1 not taken.
88486 mysql_mutex_lock(&rli->data_lock);
6571
6572 /*
6573 "Coordinator::commit_positions"
6574
6575 rli->gaq->lwm has been updated in move_queue_head() and
6576 to contain all but rli->group_master_log_name which
6577 is altered solely by Coordinator at special checkpoints.
6578 */
6579 88486 rli->set_group_master_log_pos(rli->gaq->lwm.group_master_log_pos);
6580 88486 rli->set_group_relay_log_pos(rli->gaq->lwm.group_relay_log_pos);
6581
3/8
✓ Branch 0 taken 88486 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 88486 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 88486 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
88486 DBUG_PRINT(
6582 "mts",
6583 ("New checkpoint %llu %llu %s", rli->gaq->lwm.group_master_log_pos,
6584 rli->gaq->lwm.group_relay_log_pos, rli->gaq->lwm.group_relay_log_name));
6585
6586
1/2
✓ Branch 0 taken 88486 times.
✗ Branch 1 not taken.
88486 if (rli->gaq->lwm.group_relay_log_name[0] != 0)
6587
1/2
✓ Branch 0 taken 88486 times.
✗ Branch 1 not taken.
88486 rli->set_group_relay_log_name(rli->gaq->lwm.group_relay_log_name);
6588
6589 /*
6590 todo: uncomment notifies when UNTIL will be supported
6591
6592 rli->notify_group_master_log_name_update();
6593 rli->notify_group_relay_log_name_update();
6594
6595 Todo: optimize with if (wait_flag) broadcast
6596 waiter: set wait_flag; waits....; drops wait_flag;
6597 */
6598
6599
1/2
✓ Branch 0 taken 88486 times.
✗ Branch 1 not taken.
88486 error = rli->flush_info(Relay_log_info::RLI_FLUSH_IGNORE_SYNC_OPT);
6600
6601
1/2
✓ Branch 0 taken 88486 times.
✗ Branch 1 not taken.
88486 mysql_cond_broadcast(&rli->data_cond);
6602
1/2
✓ Branch 0 taken 88486 times.
✗ Branch 1 not taken.
88486 mysql_mutex_unlock(&rli->data_lock);
6603
6604 /*
6605 We need to ensure that this is never called at this point when
6606 cnt is zero. This value means that the checkpoint information
6607 will be completely reset.
6608 */
6609
6610 /*
6611 Update the rli->last_master_timestamp for reporting correct
6612 Seconds_behind_master.
6613
6614 If GAQ is empty, set it to zero.
6615 Else, update it with the timestamp of the first job of the Slave_job_queue
6616 which was assigned in the Log_event::get_slave_worker() function.
6617 */
6618
1/2
✓ Branch 0 taken 88486 times.
✗ Branch 1 not taken.
88486 ts = rli->gaq->empty()
6619
2/2
✓ Branch 0 taken 38175 times.
✓ Branch 1 taken 50311 times.
88486 ? 0
6620
1/2
✓ Branch 0 taken 50311 times.
✗ Branch 1 not taken.
50311 : reinterpret_cast<Slave_job_group *>(rli->gaq->head_queue())->ts;
6621
1/2
✓ Branch 0 taken 88486 times.
✗ Branch 1 not taken.
88486 rli->reset_notified_checkpoint(cnt, ts, true);
6622 /* end-of "Coordinator::commit_positions" */
6623
6624 425233 end:
6625
3/4
✓ Branch 0 taken 425233 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✓ Branch 3 taken 425218 times.
425233 error = error || rli->info_thd->killed != THD::NOT_KILLED;
6626 #ifndef NDEBUG
6627
2/6
✓ Branch 0 taken 425233 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 425233 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
425233 if (DBUG_EVALUATE_IF("check_replica_debug_group", 1, 0)) DBUG_SUICIDE();
6628
4/6
✓ Branch 0 taken 425232 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 425216 times.
✓ Branch 4 taken 16 times.
✗ Branch 5 not taken.
425233 DBUG_EXECUTE_IF("mta_checkpoint", {
6629 rpl_replica_debug_point(DBUG_RPL_S_MTS_CHECKPOINT_END, rli->info_thd);
6630 };);
6631 #endif
6632
1/2
✓ Branch 0 taken 425233 times.
✗ Branch 1 not taken.
425232 set_timespec_nsec(&rli->last_clock, 0);
6633
6634 425233 return error;
6635 425233 }
6636
6637 /**
6638 Instantiation of a Slave_worker and forking out a single Worker thread.
6639
6640 @param rli Coordinator's Relay_log_info pointer
6641 @param i identifier of the Worker
6642
6643 @return 0 suppress or 1 if fails
6644 */
6645 39765 static int slave_start_single_worker(Relay_log_info *rli, ulong i) {
6646 39765 int error = 0;
6647 39765 my_thread_handle th;
6648 39765 Slave_worker *w = nullptr;
6649
6650 mysql_mutex_assert_owner(&rli->run_lock);
6651
6652
2/4
✓ Branch 0 taken 39765 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 39765 times.
39765 if (!(w = Rpl_info_factory::create_worker(opt_rli_repository_id, i, rli,
6653 false))) {
6654 LogErr(ERROR_LEVEL, ER_RPL_SLAVE_WORKER_THREAD_CREATION_FAILED,
6655 rli->get_for_channel_str());
6656 error = 1;
6657 goto err;
6658 }
6659
6660
3/4
✓ Branch 0 taken 39765 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 39764 times.
39765 if (w->init_worker(rli, i)) {
6661
9/18
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
1 LogErr(ERROR_LEVEL, ER_RPL_SLAVE_WORKER_THREAD_CREATION_FAILED,
6662 rli->get_for_channel_str());
6663 1 error = 1;
6664 1 goto err;
6665 }
6666
6667 // We assume that workers are added in sequential order here.
6668
2/4
✓ Branch 0 taken 39764 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 39764 times.
39764 assert(i == rli->workers.size());
6669
3/6
✓ Branch 0 taken 39764 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 39764 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 39764 times.
✗ Branch 5 not taken.
39764 if (i >= rli->workers.size()) rli->workers.resize(i + 1);
6670
1/2
✓ Branch 0 taken 39764 times.
✗ Branch 1 not taken.
39764 rli->workers[i] = w;
6671
6672
9/10
✓ Branch 0 taken 39764 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 39762 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 39763 times.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 39763 times.
79527 if (DBUG_EVALUATE_IF("mta_worker_thread_fails", i == 1, 0) ||
6673
2/4
✓ Branch 0 taken 39763 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 39763 times.
39763 (error = mysql_thread_create(key_thread_replica_worker, &th,
6674 &connection_attrib, handle_slave_worker,
6675 (void *)w))) {
6676
9/18
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
1 LogErr(ERROR_LEVEL, ER_RPL_SLAVE_WORKER_THREAD_CREATION_FAILED_WITH_ERRNO,
6677 rli->get_for_channel_str(), error);
6678 1 error = 1;
6679 1 goto err;
6680 }
6681
1/2
✓ Branch 0 taken 39763 times.
✗ Branch 1 not taken.
39763 mysql_mutex_lock(&w->jobs_lock);
6682
2/2
✓ Branch 0 taken 39659 times.
✓ Branch 1 taken 104 times.
39763 if (w->running_status == Slave_worker::NOT_RUNNING)
6683
1/2
✓ Branch 0 taken 39659 times.
✗ Branch 1 not taken.
39659 mysql_cond_wait(&w->jobs_cond, &w->jobs_lock);
6684
1/2
✓ Branch 0 taken 39763 times.
✗ Branch 1 not taken.
39763 mysql_mutex_unlock(&w->jobs_lock);
6685
6686 39765 err:
6687
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 39763 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
39765 if (error && w) {
6688 // Free the current submode object
6689
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 delete w->current_mts_submode;
6690 2 w->current_mts_submode = nullptr;
6691
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 delete w;
6692 /*
6693 Any failure after array inserted must follow with deletion
6694 of just created item.
6695 */
6696
4/6
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
2 if (rli->workers.size() == i + 1) rli->workers.erase(i);
6697 }
6698 39765 return error;
6699 }
6700
6701 /**
6702 Initialization of the central rli members for Coordinator's role,
6703 communication channels such as Assigned Partition Hash (APH),
6704 and starting the Worker pool.
6705
6706 @param rli Pointer to Coordinator's Relay_log_info instance.
6707 @param n Number of configured Workers in the upcoming session.
6708 @param[out] mts_inited If the initialization processed was started.
6709
6710 @return 0 success
6711 non-zero as failure
6712 */
6713 10039 static int slave_start_workers(Relay_log_info *rli, ulong n, bool *mts_inited) {
6714 10039 int error = 0;
6715 /**
6716 gtid_monitoring_info must be cleared when MTS is enabled or
6717 workers_copy_pfs has elements
6718 */
6719 10039 bool clear_gtid_monitoring_info = false;
6720
6721 mysql_mutex_assert_owner(&rli->run_lock);
6722
6723
3/4
✓ Branch 0 taken 47 times.
✓ Branch 1 taken 9992 times.
✓ Branch 2 taken 47 times.
✗ Branch 3 not taken.
10039 if (n == 0 && rli->mts_recovery_group_cnt == 0) {
6724 47 rli->workers.clear();
6725 47 rli->clear_processing_trx();
6726 47 goto end;
6727 }
6728
6729 9992 *mts_inited = true;
6730
6731 /*
6732 The requested through argument number of Workers can be different
6733 from the previous time which ended with an error. Thereby
6734 the effective number of configured Workers is max of the two.
6735 */
6736 9992 rli->init_workers(max(n, rli->recovery_parallel_workers));
6737
6738 9992 rli->last_assigned_worker = nullptr; // associated with curr_group_assigned
6739
6740 /*
6741 GAQ queue holds seqno:s of scheduled groups. C polls workers in
6742 @c opt_mta_checkpoint_period to update GAQ (see @c next_event())
6743 The length of GAQ is set to be equal to checkpoint_group.
6744 Notice, the size matters for mta_checkpoint_routine's progress loop.
6745 */
6746
6747
1/2
✓ Branch 0 taken 9992 times.
✗ Branch 1 not taken.
9992 rli->gaq = new Slave_committed_queue(rli->checkpoint_group, n);
6748
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9992 times.
9992 if (!rli->gaq->inited) return 1;
6749
6750 // length of WQ is actually constant though can be made configurable
6751 9992 rli->mts_slave_worker_queue_len_max = mts_slave_worker_queue_len_max;
6752 9992 rli->mts_pending_jobs_size = 0;
6753 9992 rli->mts_pending_jobs_size_max = ::opt_mts_pending_jobs_size_max;
6754 9992 rli->mts_wq_underrun_w_id = MTS_WORKER_UNDEF;
6755 9992 rli->mts_wq_excess_cnt = 0;
6756 9992 rli->mts_wq_overrun_cnt = 0;
6757 9992 rli->mts_wq_oversize = false;
6758 9992 rli->mts_coordinator_basic_nap = mts_coordinator_basic_nap;
6759 9992 rli->mts_worker_underrun_level = mts_worker_underrun_level;
6760 9992 rli->curr_group_seen_begin = rli->curr_group_seen_gtid = false;
6761 9992 rli->curr_group_isolated = false;
6762 9992 rli->rli_checkpoint_seqno = 0;
6763 9992 rli->mts_last_online_stat = time(nullptr);
6764 9992 rli->mts_group_status = Relay_log_info::MTS_NOT_IN_GROUP;
6765 9992 clear_gtid_monitoring_info = true;
6766
6767
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9992 times.
9992 if (init_hash_workers(rli)) // MTS: mapping_db_to_worker
6768 {
6769 LogErr(ERROR_LEVEL, ER_RPL_SLAVE_FAILED_TO_INIT_PARTITIONS_HASH);
6770 error = 1;
6771 goto err;
6772 }
6773
6774
2/2
✓ Branch 0 taken 39765 times.
✓ Branch 1 taken 9990 times.
49755 for (uint i = 0; i < n; i++) {
6775
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 39763 times.
39765 if ((error = slave_start_single_worker(rli, i))) goto err;
6776 39763 rli->replica_parallel_workers++;
6777 }
6778
6779 9990 end:
6780 /*
6781 Free the buffer that was being used to report worker's status through
6782 the table performance_schema.table_replication_applier_status_by_worker
6783 between stop slave and next start slave.
6784 */
6785
2/2
✓ Branch 0 taken 16789 times.
✓ Branch 1 taken 10037 times.
26826 for (int i = static_cast<int>(rli->workers_copy_pfs.size()) - 1; i >= 0;
6786 i--) {
6787
1/2
✓ Branch 0 taken 16789 times.
✗ Branch 1 not taken.
16789 delete rli->workers_copy_pfs[i];
6788
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 16778 times.
16789 if (!clear_gtid_monitoring_info) clear_gtid_monitoring_info = true;
6789 }
6790 10037 rli->workers_copy_pfs.clear();
6791
6792 // Effective end of the recovery right now when there is no gaps
6793
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 10037 times.
✓ Branch 2 taken 224 times.
✓ Branch 3 taken 9813 times.
10037 if (!error && rli->mts_recovery_group_cnt == 0) {
6794
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 9812 times.
9813 if ((error = rli->mts_finalize_recovery()))
6795 1 (void)Rpl_info_factory::reset_workers(rli);
6796
2/2
✓ Branch 0 taken 9812 times.
✓ Branch 1 taken 1 times.
9813 if (!error)
6797 9812 error = rli->flush_info(Relay_log_info::RLI_FLUSH_IGNORE_SYNC_OPT);
6798 }
6799
6800 224 err:
6801
2/2
✓ Branch 0 taken 10003 times.
✓ Branch 1 taken 36 times.
10039 if (clear_gtid_monitoring_info) rli->clear_gtid_monitoring_info();
6802 10039 return error;
6803 }
6804
6805 /*
6806 Ending Worker threads.
6807
6808 Not in case Coordinator is killed itself, it first waits for
6809 Workers have finished their assignments, and then updates checkpoint.
6810 Workers are notified with setting KILLED status
6811 and waited for their acknowledgment as specified by
6812 worker's running_status.
6813 Coordinator finalizes with its MTS running status to reset few objects.
6814 */
6815 9699 static void slave_stop_workers(Relay_log_info *rli, bool *mts_inited) {
6816 #ifdef WITH_WSREP
6817
1/2
✓ Branch 0 taken 9699 times.
✗ Branch 1 not taken.
9699 DBUG_TRACE;
6818 #endif /* WITH_WSREP */
6819 9699 THD *thd = rli->info_thd;
6820
6821
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 9635 times.
9699 if (!*mts_inited)
6822 64 return;
6823
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 9634 times.
9635 else if (rli->replica_parallel_workers == 0)
6824 1 goto end;
6825
6826 /*
6827 If request for stop slave is received notify worker
6828 to stop.
6829 */
6830 // Initialize worker exit count and max_updated_index to 0 during each stop.
6831 9634 rli->exit_counter = 0;
6832 19268 rli->max_updated_index = (rli->until_condition != Relay_log_info::UNTIL_NONE)
6833
2/2
✓ Branch 0 taken 1517 times.
✓ Branch 1 taken 8117 times.
9634 ? rli->mts_groups_assigned
6834 : 0;
6835
2/4
✓ Branch 0 taken 9634 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9634 times.
✗ Branch 3 not taken.
9634 if (!rli->workers.empty()) {
6836
3/4
✓ Branch 0 taken 9634 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 38335 times.
✓ Branch 3 taken 9634 times.
47969 for (int i = static_cast<int>(rli->workers.size()) - 1; i >= 0; i--) {
6837
1/2
✓ Branch 0 taken 38335 times.
✗ Branch 1 not taken.
38335 Slave_worker *w = rli->workers[i];
6838 38335 struct slave_job_item item = {nullptr, 0, 0};
6839 38335 struct slave_job_item *job_item = &item;
6840
1/2
✓ Branch 0 taken 38335 times.
✗ Branch 1 not taken.
38335 mysql_mutex_lock(&w->jobs_lock);
6841
6842
2/2
✓ Branch 0 taken 767 times.
✓ Branch 1 taken 37568 times.
38335 if (w->running_status != Slave_worker::RUNNING) {
6843
1/2
✓ Branch 0 taken 767 times.
✗ Branch 1 not taken.
767 mysql_mutex_unlock(&w->jobs_lock);
6844 767 continue;
6845 }
6846
6847 37568 w->running_status = Slave_worker::STOP;
6848
1/2
✓ Branch 0 taken 37568 times.
✗ Branch 1 not taken.
37568 (void)set_max_updated_index_on_stop(w, job_item);
6849
1/2
✓ Branch 0 taken 37568 times.
✗ Branch 1 not taken.
37568 mysql_cond_signal(&w->jobs_cond);
6850
6851
1/2
✓ Branch 0 taken 37568 times.
✗ Branch 1 not taken.
37568 mysql_mutex_unlock(&w->jobs_lock);
6852
6853
3/10
✓ Branch 0 taken 37568 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 37568 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 37568 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
37568 DBUG_PRINT("info", ("Notifying worker %lu%s to exit, thd %p", w->id,
6854 w->get_for_channel_str(), w->info_thd));
6855 }
6856 }
6857
1/2
✓ Branch 0 taken 9634 times.
✗ Branch 1 not taken.
9634 thd_proc_info(thd, "Waiting for workers to exit");
6858
6859
4/6
✓ Branch 0 taken 9634 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 47969 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 38335 times.
✓ Branch 5 taken 9634 times.
47969 for (Slave_worker **it = rli->workers.begin(); it != rli->workers.end();
6860 ++it) {
6861 38335 Slave_worker *w = *it;
6862
1/2
✓ Branch 0 taken 38335 times.
✗ Branch 1 not taken.
38335 mysql_mutex_lock(&w->jobs_lock);
6863
2/2
✓ Branch 0 taken 14386 times.
✓ Branch 1 taken 38335 times.
52721 while (w->running_status != Slave_worker::NOT_RUNNING) {
6864 14386 PSI_stage_info old_stage;
6865
5/6
✓ Branch 0 taken 14257 times.
✓ Branch 1 taken 129 times.
✓ Branch 2 taken 12115 times.
✓ Branch 3 taken 2142 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 12115 times.
14386 assert(w->running_status == Slave_worker::ERROR_LEAVING ||
6866 w->running_status == Slave_worker::STOP ||
6867 w->running_status == Slave_worker::STOP_ACCEPTED);
6868
6869
1/2
✓ Branch 0 taken 14386 times.
✗ Branch 1 not taken.
14386 thd->ENTER_COND(&w->jobs_cond, &w->jobs_lock,
6870 &stage_replica_waiting_workers_to_exit, &old_stage);
6871
1/2
✓ Branch 0 taken 14386 times.
✗ Branch 1 not taken.
14386 mysql_cond_wait(&w->jobs_cond, &w->jobs_lock);
6872
1/2
✓ Branch 0 taken 14386 times.
✗ Branch 1 not taken.
14386 mysql_mutex_unlock(&w->jobs_lock);
6873
1/2
✓ Branch 0 taken 14386 times.
✗ Branch 1 not taken.
14386 thd->EXIT_COND(&old_stage);
6874
1/2
✓ Branch 0 taken 14386 times.
✗ Branch 1 not taken.
14386 mysql_mutex_lock(&w->jobs_lock);
6875 }
6876
1/2
✓ Branch 0 taken 38335 times.
✗ Branch 1 not taken.
38335 mysql_mutex_unlock(&w->jobs_lock);
6877 }
6878
6879
4/6
✓ Branch 0 taken 9634 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 47969 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 38335 times.
✓ Branch 5 taken 9634 times.
47969 for (Slave_worker **it = rli->workers.begin(); it != rli->workers.end();
6880 ++it) {
6881 38335 Slave_worker *w = *it;
6882
6883 /*
6884 Make copies for reporting through the performance schema tables.
6885 This is preserved until the next START SLAVE.
6886 */
6887 Slave_worker *worker_copy = new Slave_worker(
6888 nullptr,
6889 #ifdef HAVE_PSI_INTERFACE
6890 &key_relay_log_info_run_lock, &key_relay_log_info_data_lock,
6891 &key_relay_log_info_sleep_lock, &key_relay_log_info_thd_lock,
6892 &key_relay_log_info_data_cond, &key_relay_log_info_start_cond,
6893 &key_relay_log_info_stop_cond, &key_relay_log_info_sleep_cond,
6894 #endif
6895
2/4
✓ Branch 0 taken 38335 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 38335 times.
✗ Branch 3 not taken.
38335 w->id, rli->get_channel());
6896
1/2
✓ Branch 0 taken 38335 times.
✗ Branch 1 not taken.
38335 worker_copy->copy_values_for_PFS(w->id, w->running_status, w->info_thd,
6897 w->last_error(),
6898 w->get_gtid_monitoring_info());
6899
1/2
✓ Branch 0 taken 38335 times.
✗ Branch 1 not taken.
38335 rli->workers_copy_pfs.push_back(worker_copy);
6900 }
6901
6902 /// @todo: consider to propagate an error out of the function
6903
3/4
✓ Branch 0 taken 8880 times.
✓ Branch 1 taken 754 times.
✓ Branch 2 taken 8880 times.
✗ Branch 3 not taken.
9634 if (thd->killed == THD::NOT_KILLED) (void)mta_checkpoint_routine(rli, false);
6904
6905 {
6906 9634 MUTEX_LOCK(lock, &rli->data_lock);
6907
3/4
✓ Branch 0 taken 47969 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 38335 times.
✓ Branch 3 taken 9634 times.
47969 while (!rli->workers.empty()) {
6908
1/2
✓ Branch 0 taken 38335 times.
✗ Branch 1 not taken.
38335 Slave_worker *w = rli->workers.back();
6909 // Free the current submode object
6910
1/2
✓ Branch 0 taken 38335 times.
✗ Branch 1 not taken.
38335 delete w->current_mts_submode;
6911 38335 w->current_mts_submode = nullptr;
6912
1/2
✓ Branch 0 taken 38335 times.
✗ Branch 1 not taken.
38335 rli->workers.pop_back();
6913
1/2
✓ Branch 0 taken 38335 times.
✗ Branch 1 not taken.
38335 delete w;
6914 }
6915 9634 }
6916
6917 struct timespec stats_end;
6918
1/2
✓ Branch 0 taken 9634 times.
✗ Branch 1 not taken.
9634 set_timespec_nsec(&stats_end, 0);
6919
6920
3/8
✓ Branch 0 taken 9634 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9634 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 9634 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
9634 DBUG_PRINT(
6921 "info",
6922 ("Total MTS session statistics: "
6923 "events processed = %llu; "
6924 "online time = %llu "
6925 "worker queues filled over overrun level = %lu "
6926 "waited due a Worker queue full = %lu "
6927 "waited due the total size = %lu "
6928 "total wait at clock conflicts = %llu "
6929 "found (count) workers occupied = %lu "
6930 "waited when workers occupied = %llu",
6931 rli->mts_events_assigned, diff_timespec(&stats_end, &rli->stats_begin),
6932 rli->mts_wq_overrun_cnt, rli->mts_wq_overfill_cnt,
6933 rli->wq_size_waits_cnt, rli->mts_total_wait_overlap.load(),
6934 rli->mts_wq_no_underrun_cnt, rli->mts_total_wait_worker_avail));
6935
6936
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9634 times.
9634 assert(rli->pending_jobs == 0);
6937
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9634 times.
9634 assert(rli->mts_pending_jobs_size == 0);
6938
6939 9635 end:
6940 9635 rli->mts_group_status = Relay_log_info::MTS_NOT_IN_GROUP;
6941
1/2
✓ Branch 0 taken 9635 times.
✗ Branch 1 not taken.
9635 destroy_hash_workers(rli);
6942
1/2
✓ Branch 0 taken 9635 times.
✗ Branch 1 not taken.
9635 delete rli->gaq;
6943
6944 // Destroy buffered events of the current group prior to exit.
6945
3/4
✓ Branch 0 taken 9673 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 38 times.
✓ Branch 3 taken 9635 times.
9673 for (uint i = 0; i < rli->curr_group_da.size(); i++)
6946
2/4
✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 38 times.
✗ Branch 3 not taken.
38 delete rli->curr_group_da[i].data;
6947
1/2
✓ Branch 0 taken 9635 times.
✗ Branch 1 not taken.
9635 rli->curr_group_da.clear(); // GCDA
6948
6949
1/2
✓ Branch 0 taken 9635 times.
✗ Branch 1 not taken.
9635 rli->curr_group_assigned_parts.clear(); // GCAP
6950
1/2
✓ Branch 0 taken 9635 times.
✗ Branch 1 not taken.
9635 rli->deinit_workers();
6951 9635 rli->workers_array_initialized = false;
6952 9635 rli->replica_parallel_workers = 0;
6953
6954 9635 *mts_inited = false;
6955
2/2
✓ Branch 0 taken 9635 times.
✓ Branch 1 taken 64 times.
9699 }
6956
6957 /**
6958 Processes the outcome of applying an event, logs it properly if it's an error
6959 and return the proper error code to trigger.
6960
6961 @return the error code to bubble up in the execution stack.
6962 */
6963 65 static int report_apply_event_error(THD *thd, Relay_log_info *rli) {
6964
1/2
✓ Branch 0 taken 65 times.
✗ Branch 1 not taken.
65 DBUG_TRACE;
6965 65 longlong slave_errno = 0;
6966
6967 /*
6968 retrieve as much info as possible from the thd and, error
6969 codes and warnings and print this to the error log as to
6970 allow the user to locate the error
6971 */
6972 65 uint32 const last_errno = rli->last_error().number;
6973
6974
3/4
✓ Branch 0 taken 65 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 61 times.
65 if (thd->is_error()) {
6975 4 char const *const errmsg = thd->get_stmt_da()->message_text();
6976
6977
3/8
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 4 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
4 DBUG_PRINT("info", ("thd->get_stmt_da()->get_mysql_errno()=%d; "
6978 "rli->last_error.number=%d",
6979 thd->get_stmt_da()->mysql_errno(), last_errno));
6980
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (last_errno == 0) {
6981 /*
6982 This function is reporting an error which was not reported
6983 while executing exec_relay_log_event().
6984 */
6985 rli->report(ERROR_LEVEL, thd->get_stmt_da()->mysql_errno(), "%s", errmsg);
6986
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 } else if (last_errno != thd->get_stmt_da()->mysql_errno()) {
6987 /*
6988 * An error was reported while executing exec_relay_log_event()
6989 * however the error code differs from what is in the thread.
6990 * This function prints out more information to help finding
6991 * what caused the problem.
6992 */
6993
8/16
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 2 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 2 times.
✗ Branch 15 not taken.
2 LogErr(ERROR_LEVEL, ER_RPL_SLAVE_ADDITIONAL_ERROR_INFO_FROM_DA, errmsg,
6994 thd->get_stmt_da()->mysql_errno());
6995 }
6996 }
6997
6998 /* Print any warnings issued */
6999 Diagnostics_area::Sql_condition_iterator it =
7000
1/2
✓ Branch 0 taken 65 times.
✗ Branch 1 not taken.
65 thd->get_stmt_da()->sql_conditions();
7001 const Sql_condition *err;
7002 /*
7003 Added controlled slave thread cancel for replication
7004 of user-defined variables.
7005 */
7006 65 bool udf_error = false;
7007
3/4
✓ Branch 0 taken 69 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 65 times.
69 while ((err = it++)) {
7008
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (err->mysql_errno() == ER_CANT_OPEN_LIBRARY) udf_error = true;
7009
8/16
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 4 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 4 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 4 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 4 times.
✗ Branch 15 not taken.
4 LogErr(WARNING_LEVEL, ER_RPL_SLAVE_ERROR_INFO_FROM_DA, err->message_text(),
7010 err->mysql_errno());
7011 }
7012
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
65 if (udf_error)
7013 slave_errno = ER_RPL_SLAVE_ERROR_LOADING_USER_DEFINED_LIBRARY;
7014 else
7015 65 slave_errno = ER_RPL_SLAVE_ERROR_RUNNING_QUERY;
7016
7017 65 return slave_errno;
7018 65 }
7019
7020 /**
7021 Slave SQL thread entry point.
7022
7023 @param arg Pointer to Relay_log_info object that holds information
7024 for the SQL thread.
7025
7026 @return Always 0.
7027 */
7028 10056 extern "C" void *handle_slave_sql(void *arg) {
7029 THD *thd; /* needs to be first for thread_stack */
7030 10056 bool thd_added = false;
7031 10056 bool main_loop_error = false;
7032 char llbuff[22], llbuff1[22];
7033 char saved_log_name[FN_REFLEN];
7034 char saved_master_log_name[FN_REFLEN];
7035 10056 my_off_t saved_log_pos = 0;
7036 10056 my_off_t saved_master_log_pos = 0;
7037 10056 my_off_t saved_skip = 0;
7038 #ifdef WITH_WSREP
7039 10056 bool wsrep_node_dropped = false;
7040 #endif /* WITH_WSREP */
7041
7042 10056 Relay_log_info *rli = ((Master_info *)arg)->rli;
7043 const char *errmsg;
7044 10056 longlong slave_errno = 0;
7045 10056 bool mts_inited = false;
7046 10056 Global_THD_manager *thd_manager = Global_THD_manager::get_instance();
7047 10056 Commit_order_manager *commit_order_mngr = nullptr;
7048
1/2
✓ Branch 0 taken 10056 times.
✗ Branch 1 not taken.
10056 Rpl_applier_reader applier_reader(rli);
7049 10056 Relay_log_info::enum_priv_checks_status priv_check_status =
7050 Relay_log_info::enum_priv_checks_status::SUCCESS;
7051
7052 // needs to call my_thread_init(), otherwise we get a coredump in DBUG_ stuff
7053
1/2
✓ Branch 0 taken 10056 times.
✗ Branch 1 not taken.
10056 my_thread_init();
7054 #ifdef WITH_WSREP
7055 10056 wsrep_restart_point :
7056 #endif /* WITH_WSREP */
7057 {
7058
1/2
✓ Branch 0 taken 10056 times.
✗ Branch 1 not taken.
10056 DBUG_TRACE;
7059
7060
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10056 times.
10056 assert(rli->inited);
7061
1/2
✓ Branch 0 taken 10056 times.
✗ Branch 1 not taken.
10056 mysql_mutex_lock(&rli->run_lock);
7062
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10056 times.
10056 assert(!rli->slave_running);
7063 10056 errmsg = nullptr;
7064 #ifndef NDEBUG
7065 10056 rli->events_until_exit = abort_slave_event_count;
7066 #endif
7067
7068
2/4
✓ Branch 0 taken 10056 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10056 times.
✗ Branch 3 not taken.
10056 thd = new THD; // note that constructor of THD uses DBUG_ !
7069 10056 thd->thread_stack = (char *)&thd; // remember where our stack is
7070
1/2
✓ Branch 0 taken 10056 times.
✗ Branch 1 not taken.
10056 mysql_mutex_lock(&rli->info_thd_lock);
7071 10056 rli->info_thd = thd;
7072
7073 #ifdef HAVE_PSI_THREAD_INTERFACE
7074 // save the instrumentation for SQL thread in rli->info_thd
7075
1/2
✓ Branch 0 taken 10056 times.
✗ Branch 1 not taken.
10056 struct PSI_thread *psi = PSI_THREAD_CALL(get_thread)();
7076
1/2
✓ Branch 0 taken 10056 times.
✗ Branch 1 not taken.
10056 thd_set_psi(rli->info_thd, psi);
7077 #endif
7078
1/2
✓ Branch 0 taken 10056 times.
✗ Branch 1 not taken.
10056 mysql_thread_set_psi_THD(thd);
7079
7080
2/2
✓ Branch 0 taken 10009 times.
✓ Branch 1 taken 47 times.
10056 if (rli->channel_mts_submode != MTS_PARALLEL_TYPE_DB_NAME)
7081
2/4
✓ Branch 0 taken 10009 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10009 times.
✗ Branch 3 not taken.
10009 rli->current_mts_submode = new Mts_submode_logical_clock();
7082 else
7083
1/2
✓ Branch 0 taken 47 times.
✗ Branch 1 not taken.
47 rli->current_mts_submode = new Mts_submode_database();
7084
7085 // Only use replica preserve commit order if more than 1 worker exists
7086
6/8
✓ Branch 0 taken 9910 times.
✓ Branch 1 taken 146 times.
✓ Branch 2 taken 9910 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9910 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 9838 times.
✓ Branch 7 taken 218 times.
19966 if (opt_replica_preserve_commit_order && !rli->is_parallel_exec() &&
7087
2/2
✓ Branch 0 taken 9838 times.
✓ Branch 1 taken 72 times.
9910 rli->opt_replica_parallel_workers > 1)
7088 9838 commit_order_mngr =
7089
2/4
✓ Branch 0 taken 9838 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9838 times.
✗ Branch 3 not taken.
9838 new Commit_order_manager(rli->opt_replica_parallel_workers);
7090
7091 10056 rli->set_commit_order_manager(commit_order_mngr);
7092
7093
3/4
✓ Branch 0 taken 10056 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3652 times.
✓ Branch 3 taken 6404 times.
10056 if (channel_map.is_group_replication_channel_name(rli->get_channel())) {
7094
3/4
✓ Branch 0 taken 3652 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2315 times.
✓ Branch 3 taken 1337 times.
3652 if (channel_map.is_group_replication_channel_name(rli->get_channel(),
7095 true)) {
7096 2315 thd->rpl_thd_ctx.set_rpl_channel_type(GR_APPLIER_CHANNEL);
7097 } else {
7098 1337 thd->rpl_thd_ctx.set_rpl_channel_type(GR_RECOVERY_CHANNEL);
7099 }
7100 } else {
7101 6404 thd->rpl_thd_ctx.set_rpl_channel_type(RPL_STANDARD_CHANNEL);
7102 }
7103
7104
1/2
✓ Branch 0 taken 10056 times.
✗ Branch 1 not taken.
10056 mysql_mutex_unlock(&rli->info_thd_lock);
7105
7106 /* Inform waiting threads that slave has started */
7107 10056 rli->slave_run_id++;
7108 10056 rli->slave_running = 1;
7109 10056 rli->reported_unsafe_warning = false;
7110 10056 rli->sql_thread_kill_accepted = false;
7111
7112
3/4
✓ Branch 0 taken 10056 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 10050 times.
10056 if (init_replica_thread(thd, SLAVE_THD_SQL)) {
7113 /*
7114 TODO: this is currently broken - slave start and change master
7115 will be stuck if we fail here
7116 */
7117
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 mysql_cond_broadcast(&rli->start_cond);
7118
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 mysql_mutex_unlock(&rli->run_lock);
7119
2/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
6 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
7120 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
7121 "Failed during slave thread initialization");
7122 6 goto err;
7123 }
7124
1/2
✓ Branch 0 taken 10050 times.
✗ Branch 1 not taken.
10050 thd->init_query_mem_roots();
7125
7126
3/4
✓ Branch 0 taken 10050 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 184 times.
✓ Branch 3 taken 9866 times.
10050 if ((rli->deferred_events_collecting = rli->rpl_filter->is_on()))
7127
2/4
✓ Branch 0 taken 184 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 184 times.
✗ Branch 3 not taken.
184 rli->deferred_events = new Deferred_log_events();
7128 10050 thd->rli_slave = rli;
7129
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10050 times.
10050 assert(thd->rli_slave->info_thd == thd);
7130
7131 10050 thd->temporary_tables = rli->save_temporary_tables; // restore temp tables
7132
1/2
✓ Branch 0 taken 10050 times.
✗ Branch 1 not taken.
10050 set_thd_in_use_temporary_tables(
7133 rli); // (re)set sql_thd in use for saved temp tables
7134 /* Set applier thread InnoDB priority */
7135
1/2
✓ Branch 0 taken 10050 times.
✗ Branch 1 not taken.
10050 set_thd_tx_priority(thd, rli->get_thd_tx_priority());
7136
7137 /* Set write set related options */
7138
1/2
✓ Branch 0 taken 10050 times.
✗ Branch 1 not taken.
10050 set_thd_write_set_options(thd, rli->get_ignore_write_set_memory_limit(),
7139 10050 rli->get_allow_drop_write_set());
7140
7141
1/2
✓ Branch 0 taken 10050 times.
✗ Branch 1 not taken.
10050 thd->variables.require_row_format = rli->is_row_format_required();
7142
7143 10050 if (Relay_log_info::PK_CHECK_STREAM !=
7144
3/4
✓ Branch 0 taken 10050 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✓ Branch 3 taken 10033 times.
10050 rli->get_require_table_primary_key_check())
7145 17 thd->variables.sql_require_primary_key =
7146
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 (rli->get_require_table_primary_key_check() ==
7147 Relay_log_info::PK_CHECK_ON);
7148
7149 // Replicas shall not create GIPKs if source tables have no PKs
7150 10050 thd->variables.sql_generate_invisible_primary_key = false;
7151
7152
1/2
✓ Branch 0 taken 10050 times.
✗ Branch 1 not taken.
10050 rli->transaction_parser.reset();
7153
7154
1/2
✓ Branch 0 taken 10050 times.
✗ Branch 1 not taken.
10050 thd_manager->add_thd(thd);
7155 10050 thd_added = true;
7156
7157 10050 rli->stats_exec_time = rli->stats_read_time = 0;
7158
1/2
✓ Branch 0 taken 10050 times.
✗ Branch 1 not taken.
10050 set_timespec_nsec(&rli->ts_exec[0], 0);
7159
1/2
✓ Branch 0 taken 10050 times.
✗ Branch 1 not taken.
10050 set_timespec_nsec(&rli->ts_exec[1], 0);
7160
1/2
✓ Branch 0 taken 10050 times.
✗ Branch 1 not taken.
10050 set_timespec_nsec(&rli->stats_begin, 0);
7161
7162
6/8
✓ Branch 0 taken 10050 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6141 times.
✓ Branch 3 taken 3909 times.
✓ Branch 4 taken 3909 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 11 times.
✓ Branch 7 taken 10039 times.
10050 if (RUN_HOOK(binlog_relay_io, applier_start, (thd, rli->mi))) {
7163
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 mysql_cond_broadcast(&rli->start_cond);
7164
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 mysql_mutex_unlock(&rli->run_lock);
7165
2/4
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
11 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
7166 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
7167 "Failed to run 'applier_start' hook");
7168 11 goto err;
7169 }
7170
7171 #ifdef WITH_WSREP
7172 /* Initialization of Galera/WSREP and async replication happens in parallel.
7173 Allow async replication infrastructure to init up to this point, but
7174 wait with applying async-replicated events until WSREP infrastructure
7175 is fully initialized (wsrep_ready == true). wsrep_ready is set when
7176 server state shifts to s_synced.
7177 Before this state, events are rejected with error
7178 'WSREP has not yet prepared node for application use' */
7179
6/8
✓ Branch 0 taken 10039 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 167 times.
✓ Branch 3 taken 9872 times.
✓ Branch 4 taken 20 times.
✓ Branch 5 taken 147 times.
✓ Branch 6 taken 20 times.
✗ Branch 7 not taken.
10039 if (WSREP(thd)) {
7180
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 Wsrep_server_state::instance().wait_until_state(
7181 Wsrep_server_state::s_synced);
7182 }
7183 #endif /* WITH_WSREP */
7184
7185 /* MTS: starting the worker pool */
7186
1/2
✓ Branch 0 taken 10039 times.
✗ Branch 1 not taken.
10039 if (slave_start_workers(rli, rli->opt_replica_parallel_workers,
7187
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 10036 times.
10039 &mts_inited) != 0) {
7188
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 mysql_cond_broadcast(&rli->start_cond);
7189
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 mysql_mutex_unlock(&rli->run_lock);
7190
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
7191 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
7192 "Failed during slave workers initialization");
7193 3 goto err;
7194 }
7195 /*
7196 We are going to set slave_running to 1. Assuming slave I/O thread is
7197 alive and connected, this is going to make Seconds_Behind_Master be 0
7198 i.e. "caught up". Even if we're just at start of thread. Well it's ok, at
7199 the moment we start we can think we are caught up, and the next second we
7200 start receiving data so we realize we are not caught up and
7201 Seconds_Behind_Master grows. No big deal.
7202 */
7203 10036 rli->abort_slave = false;
7204
7205 /*
7206 Reset errors for a clean start (otherwise, if the master is idle, the SQL
7207 thread may execute no Query_log_event, so the error will remain even
7208 though there's no problem anymore). Do not reset the master timestamp
7209 (imagine the slave has caught everything, the STOP SLAVE and START SLAVE:
7210 as we are not sure that we are going to receive a query, we want to
7211 remember the last master timestamp (to say how many seconds behind we are
7212 now.
7213 But the master timestamp is reset by RESET SLAVE & CHANGE MASTER.
7214 */
7215
1/2
✓ Branch 0 taken 10036 times.
✗ Branch 1 not taken.
10036 rli->clear_error();
7216
2/2
✓ Branch 0 taken 9989 times.
✓ Branch 1 taken 47 times.
10036 if (rli->workers_array_initialized) {
7217
3/4
✓ Branch 0 taken 49749 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 39760 times.
✓ Branch 3 taken 9989 times.
49749 for (size_t i = 0; i < rli->get_worker_count(); i++) {
7218
2/4
✓ Branch 0 taken 39760 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 39760 times.
✗ Branch 3 not taken.
39760 rli->get_worker(i)->clear_error();
7219 }
7220 }
7221
3/6
✓ Branch 0 taken 10036 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10036 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 10036 times.
20072 if (rli->update_is_transactional() ||
7222
2/4
✓ Branch 0 taken 10036 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10036 times.
10036 DBUG_EVALUATE_IF("simulate_update_is_transactional_error", true,
7223 false)) {
7224 mysql_cond_broadcast(&rli->start_cond);
7225 mysql_mutex_unlock(&rli->run_lock);
7226 rli->report(
7227 ERROR_LEVEL, ER_SLAVE_FATAL_ERROR, ER_THD(thd, ER_SLAVE_FATAL_ERROR),
7228 "Error checking if the relay log repository is transactional.");
7229 goto err;
7230 }
7231
7232
2/4
✓ Branch 0 taken 10036 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10036 times.
10036 if (rli->update_is_transactional()) {
7233 mysql_cond_broadcast(&rli->start_cond);
7234 mysql_mutex_unlock(&rli->run_lock);
7235 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
7236 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
7237 "Error checking if the relay log repository is transactional.");
7238 goto err;
7239 }
7240
7241
3/4
✓ Branch 0 taken 10036 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 64 times.
✓ Branch 3 taken 9972 times.
10036 if (!rli->is_transactional())
7242
1/2
✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
64 rli->report(WARNING_LEVEL, 0,
7243 "If a crash happens this configuration does not guarantee that "
7244 "the relay "
7245 "log info will be consistent");
7246
7247
1/2
✓ Branch 0 taken 10036 times.
✗ Branch 1 not taken.
10036 mysql_cond_broadcast(&rli->start_cond);
7248
1/2
✓ Branch 0 taken 10036 times.
✗ Branch 1 not taken.
10036 mysql_mutex_unlock(&rli->run_lock);
7249
7250
2/4
✓ Branch 0 taken 10036 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10036 times.
✗ Branch 3 not taken.
10036 DEBUG_SYNC(thd, "after_start_replica");
7251
7252 // tell the I/O thread to take relay_log_space_limit into account from now
7253 // on
7254
1/2
✓ Branch 0 taken 10036 times.
✗ Branch 1 not taken.
10036 mysql_mutex_lock(&rli->log_space_lock);
7255 10036 rli->ignore_log_space_limit = false;
7256
1/2
✓ Branch 0 taken 10036 times.
✗ Branch 1 not taken.
10036 mysql_mutex_unlock(&rli->log_space_lock);
7257 10036 rli->trans_retries = 0; // start from "no error"
7258
3/8
✓ Branch 0 taken 10036 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10036 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 10036 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
10036 DBUG_PRINT("info", ("rli->trans_retries: %lu", rli->trans_retries));
7259
7260
3/4
✓ Branch 0 taken 10036 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 10030 times.
10036 if (applier_reader.open(&errmsg)) {
7261
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR, "%s", errmsg);
7262 6 goto err;
7263 }
7264
7265
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10030 times.
10030 THD_CHECK_SENTRY(thd);
7266
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10030 times.
10030 assert(rli->info_thd == thd);
7267
7268
3/10
✓ Branch 0 taken 10030 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10030 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 10030 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
10030 DBUG_PRINT("master_info", ("log_file_name: %s position: %s",
7269 rli->get_group_master_log_name(),
7270 llstr(rli->get_group_master_log_pos(), llbuff)));
7271
7272
3/4
✓ Branch 0 taken 10030 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 10027 times.
10030 if (check_temp_dir(rli->slave_patternload_file, rli->get_channel())) {
7273
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 rli->report(ERROR_LEVEL, thd->get_stmt_da()->mysql_errno(),
7274 "Unable to use slave's temporary directory %s - %s",
7275 replica_load_tmpdir, thd->get_stmt_da()->message_text());
7276 3 goto err;
7277 }
7278
7279
1/2
✓ Branch 0 taken 10027 times.
✗ Branch 1 not taken.
10027 priv_check_status = rli->check_privilege_checks_user();
7280
3/4
✓ Branch 0 taken 10027 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 10026 times.
10027 if (!!priv_check_status) {
7281
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 rli->report_privilege_check_error(ERROR_LEVEL, priv_check_status,
7282 false /* to client*/);
7283
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 rli->set_privilege_checks_user_corrupted(true);
7284 1 goto err;
7285 }
7286 priv_check_status =
7287
1/2
✓ Branch 0 taken 10026 times.
✗ Branch 1 not taken.
10026 rli->initialize_applier_security_context(); // Applier security context
7288 // initialization with
7289 // `PRIVILEGE_CHECKS_USER`
7290
3/4
✓ Branch 0 taken 10026 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 10024 times.
10026 if (!!priv_check_status) {
7291
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 rli->report_privilege_check_error(ERROR_LEVEL, priv_check_status,
7292 false /* to client*/);
7293 2 goto err;
7294 }
7295
7296
3/4
✓ Branch 0 taken 10024 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9845 times.
✓ Branch 3 taken 179 times.
10024 if (rli->is_privilege_checks_user_null())
7297
11/22
✓ Branch 0 taken 9845 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9845 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9845 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 9845 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 9845 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 9845 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 9845 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 9845 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 9845 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 9845 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 9845 times.
✗ Branch 21 not taken.
9845 LogErr(INFORMATION_LEVEL, ER_RPL_SLAVE_SQL_THREAD_STARTING,
7298 rli->get_for_channel_str(), rli->get_rpl_log_name(),
7299 llstr(rli->get_group_master_log_pos(), llbuff),
7300 rli->get_group_relay_log_name(),
7301 llstr(rli->get_group_relay_log_pos(), llbuff1));
7302 else
7303
14/28
✓ Branch 0 taken 179 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 179 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 179 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 179 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 179 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 179 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 179 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 179 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 179 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 179 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 179 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 179 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 179 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 179 times.
✗ Branch 27 not taken.
179 LogErr(INFORMATION_LEVEL,
7304 ER_RPL_SLAVE_SQL_THREAD_STARTING_WITH_PRIVILEGE_CHECKS,
7305 rli->get_for_channel_str(), rli->get_rpl_log_name(),
7306 llstr(rli->get_group_master_log_pos(), llbuff),
7307 rli->get_group_relay_log_name(),
7308 llstr(rli->get_group_relay_log_pos(), llbuff1),
7309 rli->get_privilege_checks_username().c_str(),
7310 rli->get_privilege_checks_hostname().c_str(),
7311 opt_always_activate_granted_roles == 0 ? "DEFAULT" : "ALL");
7312
7313 /* execute init_replica variable */
7314
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 10010 times.
10024 if (opt_init_replica.length) {
7315
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 execute_init_command(thd, &opt_init_replica, &LOCK_sys_init_replica);
7316
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 11 times.
14 if (thd->is_slave_error) {
7317
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
6 rli->report(ERROR_LEVEL, ER_SERVER_SLAVE_INIT_QUERY_FAILED,
7318
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 ER_THD(current_thd, ER_SERVER_SLAVE_INIT_QUERY_FAILED),
7319 thd->get_stmt_da()->mysql_errno(),
7320 thd->get_stmt_da()->message_text());
7321 3 goto err;
7322 }
7323 }
7324
7325 /*
7326 First check until condition - probably there is nothing to execute. We
7327 do not want to wait for next event in this case.
7328 */
7329
1/2
✓ Branch 0 taken 10021 times.
✗ Branch 1 not taken.
10021 mysql_mutex_lock(&rli->data_lock);
7330
2/2
✓ Branch 0 taken 303 times.
✓ Branch 1 taken 9718 times.
10021 if (rli->slave_skip_counter) {
7331
1/2
✓ Branch 0 taken 303 times.
✗ Branch 1 not taken.
303 strmake(saved_log_name, rli->get_group_relay_log_name(), FN_REFLEN - 1);
7332
1/2
✓ Branch 0 taken 303 times.
✗ Branch 1 not taken.
303 strmake(saved_master_log_name, rli->get_group_master_log_name(),
7333 FN_REFLEN - 1);
7334 303 saved_log_pos = rli->get_group_relay_log_pos();
7335 303 saved_master_log_pos = rli->get_group_master_log_pos();
7336 303 saved_skip = rli->slave_skip_counter;
7337 }
7338
3/4
✓ Branch 0 taken 10021 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 31 times.
✓ Branch 3 taken 9990 times.
10021 if (rli->is_until_satisfied_at_start_slave()) {
7339
1/2
✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
31 mysql_mutex_unlock(&rli->data_lock);
7340 31 goto err;
7341 }
7342
1/2
✓ Branch 0 taken 9990 times.
✗ Branch 1 not taken.
9990 mysql_mutex_unlock(&rli->data_lock);
7343
7344 #ifdef WITH_WSREP
7345
1/2
✓ Branch 0 taken 9990 times.
✗ Branch 1 not taken.
9990 wsrep_open(thd);
7346
2/4
✓ Branch 0 taken 9990 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9990 times.
9990 if (wsrep_before_command(thd)) {
7347 WSREP_WARN("Slave SQL wsrep_before_command() failed");
7348 goto err;
7349 }
7350 #endif /* WITH_WSREP */
7351
7352 /* Read queries from the IO/THREAD until this thread is killed */
7353
7354
7/8
✓ Branch 0 taken 1659310 times.
✓ Branch 1 taken 8200 times.
✓ Branch 2 taken 1659310 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1657877 times.
✓ Branch 5 taken 1433 times.
✓ Branch 6 taken 1657877 times.
✓ Branch 7 taken 9633 times.
1667510 while (!main_loop_error && !sql_slave_killed(thd, rli)) {
7355 1657877 Log_event *ev = nullptr;
7356
1/2
✓ Branch 0 taken 1657877 times.
✗ Branch 1 not taken.
1657877 THD_STAGE_INFO(thd, stage_reading_event_from_the_relay_log);
7357
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1657877 times.
1657877 assert(rli->info_thd == thd);
7358
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1657877 times.
1657877 THD_CHECK_SENTRY(thd);
7359
6/6
✓ Branch 0 taken 1932 times.
✓ Branch 1 taken 1655945 times.
✓ Branch 2 taken 302 times.
✓ Branch 3 taken 1630 times.
✓ Branch 4 taken 302 times.
✓ Branch 5 taken 1657575 times.
1657877 if (saved_skip && rli->slave_skip_counter == 0) {
7360
8/16
✓ Branch 0 taken 302 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 302 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 302 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 302 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 302 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 302 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 302 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 302 times.
✗ Branch 15 not taken.
302 LogErr(INFORMATION_LEVEL, ER_RPL_SLAVE_SKIP_COUNTER_EXECUTED,
7361 (ulong)saved_skip, saved_log_name, (ulong)saved_log_pos,
7362 saved_master_log_name, (ulong)saved_master_log_pos,
7363 rli->get_group_relay_log_name(),
7364 (ulong)rli->get_group_relay_log_pos(),
7365 rli->get_group_master_log_name_info(),
7366 (ulong)rli->get_group_master_log_pos_info());
7367 302 saved_skip = 0;
7368 }
7369
7370 // read next event
7371
1/2
✓ Branch 0 taken 1657877 times.
✗ Branch 1 not taken.
1657877 mysql_mutex_lock(&rli->data_lock);
7372
1/2
✓ Branch 0 taken 1657730 times.
✗ Branch 1 not taken.
1657877 ev = applier_reader.read_next_event();
7373
1/2
✓ Branch 0 taken 1657730 times.
✗ Branch 1 not taken.
1657730 mysql_mutex_unlock(&rli->data_lock);
7374
7375 // set additional context as needed by the scheduler before execution
7376 // takes place
7377
7/8
✓ Branch 0 taken 1649672 times.
✓ Branch 1 taken 8058 times.
✓ Branch 2 taken 1649672 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1646117 times.
✓ Branch 5 taken 3555 times.
✓ Branch 6 taken 1646117 times.
✓ Branch 7 taken 11613 times.
3303847 if (ev != nullptr && rli->is_parallel_exec() &&
7378
1/2
✓ Branch 0 taken 1646117 times.
✗ Branch 1 not taken.
1646117 rli->current_mts_submode != nullptr)
7379
1/2
✓ Branch 0 taken 1646116 times.
✗ Branch 1 not taken.
1646117 rli->current_mts_submode->set_multi_threaded_applier_context(*rli, *ev);
7380
7381 // try to execute the event
7382
3/5
✓ Branch 0 taken 1657520 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1649321 times.
✓ Branch 3 taken 8199 times.
✗ Branch 4 not taken.
1657729 switch (exec_relay_log_event(thd, rli, &applier_reader, ev)) {
7383 1649321 case SLAVE_APPLY_EVENT_AND_UPDATE_POS_OK:
7384 /** success, we read the next event. */
7385 /** fall through */
7386 case SLAVE_APPLY_EVENT_UNTIL_REACHED:
7387 /** this will make the main loop abort in the next iteration */
7388 /** fall through */
7389 case SLAVE_APPLY_EVENT_RETRY:
7390 /** single threaded applier has to retry.
7391 Next iteration reads the same event. */
7392 1649321 break;
7393
7394 8199 case SLAVE_APPLY_EVENT_AND_UPDATE_POS_APPLY_ERROR:
7395 /** fall through */
7396 case SLAVE_APPLY_EVENT_AND_UPDATE_POS_UPDATE_POS_ERROR:
7397 /** fall through */
7398 case SLAVE_APPLY_EVENT_AND_UPDATE_POS_APPEND_JOB_ERROR:
7399 8199 main_loop_error = true;
7400 8199 break;
7401
7402 default:
7403 /* This shall never happen. */
7404 assert(0); /* purecov: inspected */
7405 break;
7406 }
7407 }
7408 9633 err:
7409
7410 // report error
7411
7412 #ifdef WITH_WSREP
7413
6/6
✓ Branch 0 taken 8199 times.
✓ Branch 1 taken 1500 times.
✓ Branch 2 taken 21 times.
✓ Branch 3 taken 8178 times.
✓ Branch 4 taken 20 times.
✓ Branch 5 taken 1 times.
9699 if (main_loop_error == true && WSREP_ON) {
7414
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 mysql_mutex_lock(&thd->LOCK_wsrep_thd);
7415
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if (thd->wsrep_cs().current_error()) {
7416 wsrep_node_dropped = true;
7417 rli->abort_slave = true;
7418 }
7419
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
7420 }
7421 #endif /* WITH_WSREP */
7422
7423
7/8
✓ Branch 0 taken 8199 times.
✓ Branch 1 taken 1500 times.
✓ Branch 2 taken 8199 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 65 times.
✓ Branch 5 taken 8134 times.
✓ Branch 6 taken 65 times.
✓ Branch 7 taken 9634 times.
9699 if (main_loop_error == true && !sql_slave_killed(thd, rli))
7424
1/2
✓ Branch 0 taken 65 times.
✗ Branch 1 not taken.
65 slave_errno = report_apply_event_error(thd, rli);
7425
7426 /* At this point the SQL thread will not try to work anymore. */
7427 9699 rli->atomic_is_stopping = true;
7428
7/10
✓ Branch 0 taken 9699 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3894 times.
✓ Branch 3 taken 5805 times.
✓ Branch 4 taken 3832 times.
✓ Branch 5 taken 62 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3832 times.
✓ Branch 8 taken 3894 times.
✗ Branch 9 not taken.
9699 (void)RUN_HOOK(
7429 binlog_relay_io, applier_stop,
7430 (thd, rli->mi, rli->is_error() || !rli->sql_thread_kill_accepted));
7431
7432
1/2
✓ Branch 0 taken 9699 times.
✗ Branch 1 not taken.
9699 slave_stop_workers(rli, &mts_inited); // stopping worker pool
7433 /* Thread stopped. Print the current replication position to the log */
7434
2/2
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 9634 times.
9699 if (slave_errno)
7435
9/18
✓ Branch 0 taken 65 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 65 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 65 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 65 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 65 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 65 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 65 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 65 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 65 times.
✗ Branch 17 not taken.
65 LogErr(ERROR_LEVEL, slave_errno, rli->get_rpl_log_name(),
7436 llstr(rli->get_group_master_log_pos(), llbuff));
7437 else
7438
10/20
✓ Branch 0 taken 9634 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9634 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9634 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 9634 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 9634 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 9634 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 9634 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 9634 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 9634 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 9634 times.
✗ Branch 19 not taken.
9634 LogErr(INFORMATION_LEVEL, ER_RPL_SLAVE_SQL_THREAD_EXITING,
7439 rli->get_for_channel_str(), rli->get_rpl_log_name(),
7440 llstr(rli->get_group_master_log_pos(), llbuff));
7441
7442 #ifdef WITH_WSREP
7443
1/2
✓ Branch 0 taken 9699 times.
✗ Branch 1 not taken.
9699 wsrep_after_command_before_result(thd);
7444
1/2
✓ Branch 0 taken 9699 times.
✗ Branch 1 not taken.
9699 wsrep_after_command_after_result(thd);
7445
1/2
✓ Branch 0 taken 9699 times.
✗ Branch 1 not taken.
9699 wsrep_close(thd);
7446 #endif /* WITH_WSREP */
7447
7448
1/2
✓ Branch 0 taken 9699 times.
✗ Branch 1 not taken.
9699 delete rli->current_mts_submode;
7449 9699 rli->current_mts_submode = 0;
7450
1/2
✓ Branch 0 taken 9699 times.
✗ Branch 1 not taken.
9699 rli->clear_mts_recovery_groups();
7451
7452 /*
7453 Some events set some playgrounds, which won't be cleared because thread
7454 stops. Stopping of this thread may not be known to these events ("stop"
7455 request is detected only by the present function, not by events), so we
7456 must "proactively" clear playgrounds:
7457 */
7458
1/2
✓ Branch 0 taken 9699 times.
✗ Branch 1 not taken.
9699 thd->clear_error();
7459
1/2
✓ Branch 0 taken 9699 times.
✗ Branch 1 not taken.
9699 rli->cleanup_context(thd, true);
7460 /*
7461 Some extra safety, which should not been needed (normally, event deletion
7462 should already have done these assignments (each event which sets these
7463 variables is supposed to set them to 0 before terminating)).
7464 */
7465 9699 thd->set_catalog(NULL_CSTR);
7466
1/2
✓ Branch 0 taken 9699 times.
✗ Branch 1 not taken.
9699 thd->reset_query();
7467
1/2
✓ Branch 0 taken 9699 times.
✗ Branch 1 not taken.
9699 thd->reset_db(NULL_CSTR);
7468
7469 /*
7470 Pause the SQL thread and wait for 'continue_to_stop_sql_thread'
7471 signal to continue to shutdown the SQL thread.
7472 */
7473
4/6
✓ Branch 0 taken 9699 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 9696 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
9699 DBUG_EXECUTE_IF("pause_after_sql_thread_stop_hook", {
7474 rpl_replica_debug_point(DBUG_RPL_S_AFTER_SQL_STOP, thd);
7475 };);
7476
7477
1/2
✓ Branch 0 taken 9699 times.
✗ Branch 1 not taken.
9699 THD_STAGE_INFO(thd, stage_waiting_for_replica_mutex_on_exit);
7478
1/2
✓ Branch 0 taken 9699 times.
✗ Branch 1 not taken.
9699 mysql_mutex_lock(&rli->run_lock);
7479 /* We need data_lock, at least to wake up any waiting source_pos_wait() */
7480
1/2
✓ Branch 0 taken 9699 times.
✗ Branch 1 not taken.
9699 mysql_mutex_lock(&rli->data_lock);
7481
1/2
✓ Branch 0 taken 9699 times.
✗ Branch 1 not taken.
9699 applier_reader.close();
7482
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9699 times.
9699 assert(rli->slave_running == 1); // tracking buffer overrun
7483 /* When source_pos_wait() wakes up it will check this and terminate */
7484 9699 rli->slave_running = 0;
7485 9699 rli->atomic_is_stopping = false;
7486 /* Forget the relay log's format */
7487
2/4
✓ Branch 0 taken 9699 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9699 times.
9699 if (rli->set_rli_description_event(nullptr)) {
7488 #ifndef NDEBUG
7489 bool set_rli_description_event_failed = false;
7490 #endif
7491 assert(set_rli_description_event_failed);
7492 }
7493 /* Wake up source_pos_wait() */
7494
3/8
✓ Branch 0 taken 9699 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9699 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 9699 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
9699 DBUG_PRINT("info",
7495 ("Signaling possibly waiting source_pos_wait() functions"));
7496
1/2
✓ Branch 0 taken 9699 times.
✗ Branch 1 not taken.
9699 mysql_cond_broadcast(&rli->data_cond);
7497
1/2
✓ Branch 0 taken 9699 times.
✗ Branch 1 not taken.
9699 mysql_mutex_unlock(&rli->data_lock);
7498 9699 rli->ignore_log_space_limit = false; /* don't need any lock */
7499 9699 rli->sql_force_rotate_relay = false;
7500 /* we die so won't remember charset - re-update them on next thread start */
7501
1/2
✓ Branch 0 taken 9699 times.
✗ Branch 1 not taken.
9699 rli->cached_charset_invalidate();
7502 9699 rli->save_temporary_tables = thd->temporary_tables;
7503
7504 /*
7505 TODO: see if we can do this conditionally in next_event() instead
7506 to avoid unneeded position re-init
7507 */
7508 9699 thd->temporary_tables =
7509 nullptr; // remove temptation from destructor to close them
7510 // destructor will not free it, because we are weird
7511
2/4
✓ Branch 0 taken 9699 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9699 times.
✗ Branch 3 not taken.
9699 thd->get_protocol_classic()->end_net();
7512
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9699 times.
9699 assert(rli->info_thd == thd);
7513
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9699 times.
9699 THD_CHECK_SENTRY(thd);
7514
1/2
✓ Branch 0 taken 9699 times.
✗ Branch 1 not taken.
9699 mysql_mutex_lock(&rli->info_thd_lock);
7515 9699 rli->info_thd = nullptr;
7516
2/2
✓ Branch 0 taken 9481 times.
✓ Branch 1 taken 218 times.
9699 if (commit_order_mngr) {
7517 9481 rli->set_commit_order_manager(nullptr);
7518
1/2
✓ Branch 0 taken 9481 times.
✗ Branch 1 not taken.
9481 delete commit_order_mngr;
7519 }
7520
7521
1/2
✓ Branch 0 taken 9699 times.
✗ Branch 1 not taken.
9699 mysql_mutex_unlock(&rli->info_thd_lock);
7522
1/2
✓ Branch 0 taken 9699 times.
✗ Branch 1 not taken.
9699 set_thd_in_use_temporary_tables(
7523 rli); // (re)set info_thd in use for saved temp tables
7524
7525
1/2
✓ Branch 0 taken 9699 times.
✗ Branch 1 not taken.
9699 thd->release_resources();
7526
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9699 times.
9699 THD_CHECK_SENTRY(thd);
7527
3/4
✓ Branch 0 taken 9693 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 9693 times.
✗ Branch 3 not taken.
9699 if (thd_added) thd_manager->remove_thd(thd);
7528
7529 /*
7530 The thd can only be destructed after indirect references
7531 through mi->rli->info_thd are cleared: mi->rli->info_thd= NULL.
7532
7533 For instance, user thread might be issuing show_slave_status
7534 and attempting to read mi->rli->info_thd->proc_info().
7535 Therefore thd must only be deleted after info_thd is set
7536 to NULL.
7537 */
7538
1/2
✓ Branch 0 taken 9699 times.
✗ Branch 1 not taken.
9699 mysql_thread_set_psi_THD(nullptr);
7539
1/2
✓ Branch 0 taken 9699 times.
✗ Branch 1 not taken.
9699 delete thd;
7540
7541 #ifdef WITH_WSREP
7542 /* if slave stopped due to node going non primary, we set global flag to
7543 trigger automatic restart of slave when node joins back to cluster
7544 */
7545
5/8
✓ Branch 0 taken 91 times.
✓ Branch 1 taken 9608 times.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 71 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 20 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
9699 if (WSREP_ON && wsrep_node_dropped && wsrep_restart_slave) {
7546 if (wsrep_ready_get()) {
7547 WSREP_INFO(
7548 "Slave error due to node temporarily went non-primary"
7549 "SQL slave will continue");
7550 wsrep_node_dropped = false;
7551 mysql_mutex_unlock(&rli->run_lock);
7552 WSREP_INFO("Restarting Slave (conflict-state: %s)",
7553 wsrep_thd_client_state_str(thd));
7554 goto wsrep_restart_point;
7555 } else {
7556 WSREP_INFO("Slave error due to node going non-primary");
7557 WSREP_INFO(
7558 "wsrep_restart_slave is set. Slave will automatically"
7559 " restart when node joins back the cluster");
7560 wsrep_restart_slave_activated = true;
7561 }
7562 }
7563 // wsrep_close(thd);
7564 #endif /* WITH_WSREP */
7565
7566 /*
7567 Note: the order of the broadcast and unlock calls below (first broadcast,
7568 then unlock) is important. Otherwise a killer_thread can execute between
7569 the calls and delete the mi structure leading to a crash! (see BUG#25306
7570 for details)
7571 */
7572
1/2
✓ Branch 0 taken 9699 times.
✗ Branch 1 not taken.
9699 mysql_cond_broadcast(&rli->stop_cond);
7573
4/6
✓ Branch 0 taken 9699 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 9696 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
9699 DBUG_EXECUTE_IF("simulate_replica_delay_at_terminate_bug38694",
7574 sleep(5););
7575
1/2
✓ Branch 0 taken 9699 times.
✗ Branch 1 not taken.
9699 mysql_mutex_unlock(&rli->run_lock); // tell the world we are done
7576
1/2
✓ Branch 0 taken 9699 times.
✗ Branch 1 not taken.
9699 }
7577
1/2
✓ Branch 0 taken 9699 times.
✗ Branch 1 not taken.
9699 my_thread_end();
7578 #if OPENSSL_VERSION_NUMBER < 0x10100000L
7579 ERR_remove_thread_state(0);
7580 #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
7581 9699 my_thread_exit(nullptr);
7582 return nullptr; // Avoid compiler warnings
7583 9699 }
7584
7585 /**
7586 Used by the slave IO thread when it receives a rotate event from the
7587 master.
7588
7589 Updates the master info with the place in the next binary log where
7590 we should start reading. Rotate the relay log to avoid mixed-format
7591 relay logs.
7592
7593 @param mi master_info for the slave
7594 @param rev The rotate log event read from the master
7595
7596 @note The caller must hold mi->data_lock before invoking this function.
7597
7598 @retval 0 ok
7599 @retval 1 error
7600 */
7601 18413 static int process_io_rotate(Master_info *mi, Rotate_log_event *rev) {
7602
1/2
✓ Branch 0 taken 18413 times.
✗ Branch 1 not taken.
18413 DBUG_TRACE;
7603 mysql_mutex_assert_owner(mi->rli->relay_log.get_log_lock());
7604
7605
2/4
✓ Branch 0 taken 18413 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 18413 times.
18413 if (unlikely(!rev->is_valid())) return 1;
7606
7607 #ifndef NDEBUG
7608 /*
7609 If we do not do this, we will be getting the first
7610 rotate event forever, so we need to not disconnect after one.
7611 */
7612
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18413 times.
18413 if (disconnect_slave_event_count) mi->events_until_exit++;
7613 #endif
7614
7615 /*
7616 Master will send a FD event immediately after the Roate event, so don't log
7617 the current FD event.
7618 */
7619
1/2
✓ Branch 0 taken 18413 times.
✗ Branch 1 not taken.
18413 int ret = rotate_relay_log(mi, false, false, true);
7620
7621
1/2
✓ Branch 0 taken 18413 times.
✗ Branch 1 not taken.
18413 mysql_mutex_lock(&mi->data_lock);
7622 /* Safe copy as 'rev' has been "sanitized" in Rotate_log_event's ctor */
7623 36826 memcpy(const_cast<char *>(mi->get_master_log_name()), rev->new_log_ident,
7624 18413 rev->ident_len + 1);
7625 18413 mi->set_master_log_pos(rev->pos);
7626
3/8
✓ Branch 0 taken 18413 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18413 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 18413 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
18413 DBUG_PRINT("info",
7627 ("new (master_log_name, master_log_pos): ('%s', %lu)",
7628 mi->get_master_log_name(), (ulong)mi->get_master_log_pos()));
7629
1/2
✓ Branch 0 taken 18413 times.
✗ Branch 1 not taken.
18413 mysql_mutex_unlock(&mi->data_lock);
7630
7631 18413 return ret;
7632 18413 }
7633
7634 2093 int heartbeat_queue_event(bool is_valid, Master_info *&mi,
7635 std::string binlog_name, uint64_t position,
7636 unsigned long &inc_pos, bool &do_flush_mi) {
7637
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2093 times.
2093 if (!is_valid) {
7638 char errbuf[1024];
7639 char llbuf[22];
7640 sprintf(errbuf,
7641 "inconsistent heartbeat event content; the event's data: "
7642 "log_file_name %-.512s log_pos %s",
7643 binlog_name.c_str(), llstr(position, llbuf));
7644 mi->report(ERROR_LEVEL, ER_SLAVE_HEARTBEAT_FAILURE,
7645 ER_THD(current_thd, ER_SLAVE_HEARTBEAT_FAILURE), errbuf);
7646 return 1;
7647 }
7648
1/2
✓ Branch 0 taken 2093 times.
✗ Branch 1 not taken.
2093 mysql_mutex_lock(&mi->data_lock);
7649 2093 mi->received_heartbeats++;
7650 2093 mi->last_heartbeat = my_getsystime() / 10;
7651 std::string mi_log_filename{
7652
2/4
✓ Branch 0 taken 2093 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2093 times.
✗ Branch 3 not taken.
2093 mi->get_master_log_name() != nullptr ? mi->get_master_log_name() : ""};
7653
7654 /*
7655 compare local and event's versions of log_file, log_pos.
7656
7657 Heartbeat is sent only after an event corresponding to the coordinates
7658 the heartbeat carries.
7659 Slave can not have a difference in coordinates except in the
7660 special case when mi->get_master_log_name(), mi->get_master_log_pos()
7661 have never been updated by Rotate event i.e when slave does not have
7662 any history with the master (and thereafter mi->get_master_log_pos() is
7663 NULL).
7664
7665 TODO: handling `when' for SHOW REPLICA STATUS' snds behind
7666 */
7667
2/4
✓ Branch 0 taken 2093 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2093 times.
2093 if (mi_log_filename.compare(binlog_name) != 0) {
7668 std::ostringstream oss;
7669 oss << "Replication heartbeat event contained the filename '" << binlog_name
7670 << "' which is different from '" << mi_log_filename
7671 << "' that was specified in earlier Rotate events.";
7672 mi->report(ERROR_LEVEL, ER_SLAVE_HEARTBEAT_FAILURE,
7673 ER_THD(current_thd, ER_SLAVE_HEARTBEAT_FAILURE),
7674 oss.str().c_str());
7675 return 1;
7676
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2093 times.
2093 } else if (mi->get_master_log_pos() > position) {
7677 std::ostringstream oss;
7678 oss << "Replication heartbeat event contained the position " << position
7679 << " which is smaller than the position " << mi->get_master_log_pos()
7680 << " that was computed from earlier events received in the stream. "
7681 << "The filename is '" << mi_log_filename << "'.";
7682 mi->report(ERROR_LEVEL, ER_SLAVE_HEARTBEAT_FAILURE,
7683 ER_THD(current_thd, ER_SLAVE_HEARTBEAT_FAILURE),
7684 oss.str().c_str());
7685 return 1;
7686 }
7687 /*
7688 During GTID protocol, if the master skips transactions,
7689 a heartbeat event is sent to the slave at the end of last
7690 skipped transaction to update coordinates.
7691
7692 I/O thread receives the heartbeat event and updates mi
7693 only if the received heartbeat position is greater than
7694 mi->get_master_log_pos(). This event is written to the
7695 relay log as an ignored Rotate event. SQL thread reads
7696 the rotate event only to update the coordinates corresponding
7697 to the last skipped transaction. Note that,
7698 we update only the positions and not the file names, as a ROTATE
7699 EVENT from the master prior to this will update the file name.
7700
7701 When master's binlog is PS 5_7 encrypted it will also sent heartbeat
7702 event after reading Start_encryption_event from the binlog.
7703 As Start_encryption_event is not sent to slave, the master
7704 informs the slave to update it's master_log_pos by sending
7705 heartbeat event.
7706 */
7707
5/6
✓ Branch 0 taken 901 times.
✓ Branch 1 taken 1192 times.
✓ Branch 2 taken 901 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 901 times.
✓ Branch 5 taken 1192 times.
2093 if (mi->get_master_log_pos() < position && !mi_log_filename.empty()) {
7708
4/6
✓ Branch 0 taken 901 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 899 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
901 DBUG_EXECUTE_IF("reached_heart_beat_queue_event",
7709 { rpl_replica_debug_point(DBUG_RPL_S_HEARTBEAT_EV); };);
7710 901 mi->set_master_log_pos(position);
7711
7712 /*
7713 Put this heartbeat event in the relay log as a Rotate Event.
7714 */
7715 901 inc_pos = 0;
7716
1/2
✓ Branch 0 taken 901 times.
✗ Branch 1 not taken.
901 mysql_mutex_unlock(&mi->data_lock);
7717
2/4
✓ Branch 0 taken 901 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 901 times.
901 if (write_rotate_to_master_pos_into_relay_log(mi->info_thd, mi, false
7718 /* force_flush_mi_info */))
7719 return 0;
7720 901 do_flush_mi = false; /* write_rotate_... above flushed master info */
7721 } else
7722
1/2
✓ Branch 0 taken 1192 times.
✗ Branch 1 not taken.
1192 mysql_mutex_unlock(&mi->data_lock);
7723
7724 2093 return 0;
7725 2093 }
7726
7727 /**
7728 Store an event received from the master connection into the relay
7729 log.
7730
7731 @param mi The Master_info object representing this connection.
7732 @param buf Pointer to the event data.
7733 @param event_len Length of event data.
7734 @param do_flush_mi True to flush master info after successfully queuing the
7735 event.
7736
7737 @retval QUEUE_EVENT_OK on success.
7738 @retval QUEUE_EVENT_ERROR_QUEUING if there was an error while queuing.
7739 @retval QUEUE_EVENT_ERROR_FLUSHING_INFO if there was an error while
7740 flushing master info.
7741
7742 @todo Make this a member of Master_info.
7743 */
7744 1566465 QUEUE_EVENT_RESULT queue_event(Master_info *mi, const char *buf,
7745 ulong event_len, bool do_flush_mi) {
7746 1566465 QUEUE_EVENT_RESULT res = QUEUE_EVENT_OK;
7747 1566465 ulong inc_pos = 0;
7748 1566465 Relay_log_info *rli = mi->rli;
7749 1566465 mysql_mutex_t *log_lock = rli->relay_log.get_log_lock();
7750 ulong s_id;
7751 1566465 int lock_count = 0;
7752
7753
7/12
✓ Branch 0 taken 1566465 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1566464 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
1566465 DBUG_EXECUTE_IF("wait_in_the_middle_of_trx", {
7754 /*
7755 See `gr_flush_relay_log_no_split_trx.test`
7756 1) Add a debug sync point that holds and makes the applier thread to
7757 wait, in the middle of a transaction -
7758 `signal.rpl_requested_for_a_flush`.
7759 */
7760 DBUG_SET("-d,wait_in_the_middle_of_trx");
7761 const char dbug_wait[] = "now WAIT_FOR signal.rpl_requested_for_a_flush";
7762 assert(!debug_sync_set_action(current_thd, STRING_WITH_LEN(dbug_wait)));
7763 });
7764
7765 /*
7766 inside get_master_version_and_clock()
7767 Show-up of FD:s affects checksum_alg at once because
7768 that changes FD_queue.
7769 */
7770 1566465 enum_binlog_checksum_alg checksum_alg =
7771 1566465 mi->checksum_alg_before_fd != binary_log::BINLOG_CHECKSUM_ALG_UNDEF
7772
2/2
✓ Branch 0 taken 237677 times.
✓ Branch 1 taken 1328788 times.
1566465 ? mi->checksum_alg_before_fd
7773 1328788 : mi->rli->relay_log.relay_log_checksum_alg;
7774
7775 1566465 const char *save_buf =
7776 nullptr; // needed for checksumming the fake Rotate event
7777 char rot_buf[LOG_EVENT_HEADER_LEN + Binary_log_event::ROTATE_HEADER_LEN +
7778 FN_REFLEN];
7779 1566465 Gtid gtid = {0, 0};
7780 1566465 ulonglong immediate_commit_timestamp = 0;
7781 1566465 ulonglong original_commit_timestamp = 0;
7782 1566465 bool info_error{false};
7783 1566465 binary_log::Log_event_basic_info log_event_info;
7784 1566465 ulonglong compressed_transaction_bytes = 0;
7785 1566465 ulonglong uncompressed_transaction_bytes = 0;
7786 1566465 auto compression_type = binary_log::transaction::compression::type::NONE;
7787 1566465 Log_event_type event_type =
7788 1566465 (Log_event_type) static_cast<uchar>(buf[EVENT_TYPE_OFFSET]);
7789
7790
4/6
✓ Branch 0 taken 1341871 times.
✓ Branch 1 taken 224594 times.
✓ Branch 2 taken 1341871 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1341871 times.
1566465 assert(checksum_alg == binary_log::BINLOG_CHECKSUM_ALG_OFF ||
7791 checksum_alg == binary_log::BINLOG_CHECKSUM_ALG_UNDEF ||
7792 checksum_alg == binary_log::BINLOG_CHECKSUM_ALG_CRC32);
7793
7794
1/2
✓ Branch 0 taken 1566465 times.
✗ Branch 1 not taken.
1566465 DBUG_TRACE;
7795
7796 /*
7797 Pause the IO thread execution and wait for 'continue_queuing_event'
7798 signal to continue IO thread execution.
7799 */
7800
4/6
✓ Branch 0 taken 1566465 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 162 times.
✓ Branch 3 taken 1566303 times.
✓ Branch 4 taken 162 times.
✗ Branch 5 not taken.
1566465 DBUG_EXECUTE_IF("pause_on_queuing_event",
7801 { rpl_replica_debug_point(DBUG_RPL_S_PAUSE_QUEUING); };);
7802
7803 /*
7804 FD_queue checksum alg description does not apply in a case of
7805 FD itself. The one carries both parts of the checksum data.
7806 */
7807
2/2
✓ Branch 0 taken 12671 times.
✓ Branch 1 taken 1553794 times.
1566465 if (event_type == binary_log::FORMAT_DESCRIPTION_EVENT) {
7808
1/2
✓ Branch 0 taken 12671 times.
✗ Branch 1 not taken.
12671 checksum_alg = Log_event_footer::get_checksum_alg(buf, event_len);
7809 }
7810
7811 // does not hold always because of old binlog can work with NM
7812 // assert(checksum_alg != BINLOG_CHECKSUM_ALG_UNDEF);
7813
7814 // should hold unless manipulations with RL. Tests that do that
7815 // will have to refine the clause.
7816
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1566465 times.
1566465 assert(mi->rli->relay_log.relay_log_checksum_alg !=
7817 binary_log::BINLOG_CHECKSUM_ALG_UNDEF);
7818
7819 // Emulate the network corruption
7820
9/18
✓ Branch 0 taken 1566465 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 1566462 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 3 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✓ Branch 16 taken 3 times.
✗ Branch 17 not taken.
1566465 DBUG_EXECUTE_IF(
7821 "corrupt_queue_event",
7822 if (event_type != binary_log::FORMAT_DESCRIPTION_EVENT &&
7823 event_type != binary_log::START_5_7_ENCRYPTION_EVENT) {
7824 char *debug_event_buf_c = const_cast<char *>(buf);
7825 int debug_cor_pos = rand() % (event_len - BINLOG_CHECKSUM_LEN);
7826 debug_event_buf_c[debug_cor_pos] = ~debug_event_buf_c[debug_cor_pos];
7827 DBUG_PRINT("info",
7828 ("Corrupt the event at queue_event: byte on position %d",
7829 debug_cor_pos));
7830 DBUG_SET("");
7831 });
7832 1566465 binary_log_debug::debug_checksum_test =
7833
1/2
✓ Branch 0 taken 1566465 times.
✗ Branch 1 not taken.
1566465 DBUG_EVALUATE_IF("simulate_checksum_test_failure", true, false);
7834
3/4
✓ Branch 0 taken 1566465 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 1566458 times.
1566465 if (Log_event_footer::event_checksum_test(
7835 1566465 const_cast<uchar *>(pointer_cast<const uchar *>(buf)), event_len,
7836 checksum_alg)) {
7837
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 mi->report(ERROR_LEVEL, ER_NETWORK_READ_EVENT_CHECKSUM_FAILURE, "%s",
7838
2/4
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
7 ER_THD(current_thd, ER_NETWORK_READ_EVENT_CHECKSUM_FAILURE));
7839 7 goto err;
7840 }
7841
7842 /*
7843 From now, and up to finishing queuing the event, no other thread is allowed
7844 to write to the relay log, or to rotate it.
7845 */
7846
1/2
✓ Branch 0 taken 1566458 times.
✗ Branch 1 not taken.
1566458 mysql_mutex_lock(log_lock);
7847
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1566458 times.
1566458 assert(lock_count == 0);
7848 1566458 lock_count = 1;
7849
7850
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1566458 times.
1566458 if (mi->get_mi_description_event() == nullptr) {
7851 LogErr(ERROR_LEVEL, ER_RPL_SLAVE_QUEUE_EVENT_FAILED_INVALID_CONFIGURATION,
7852 mi->get_channel());
7853 goto err;
7854 }
7855
7856 /*
7857 Simulate an unknown ignorable log event by rewriting a Xid
7858 log event before queuing it into relay log.
7859 */
7860
8/12
✓ Branch 0 taken 1566458 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 1566442 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 14 times.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
1566458 DBUG_EXECUTE_IF(
7861 "simulate_unknown_ignorable_log_event_with_xid",
7862 if (event_type == binary_log::XID_EVENT) {
7863 uchar *ev_buf = const_cast<uchar *>(pointer_cast<const uchar *>(buf));
7864 /* Overwrite the log event type with an unknown type. */
7865 ev_buf[EVENT_TYPE_OFFSET] = binary_log::ENUM_END_EVENT + 1;
7866 /* Set LOG_EVENT_IGNORABLE_F for the log event. */
7867 int2store(ev_buf + FLAGS_OFFSET,
7868 uint2korr(ev_buf + FLAGS_OFFSET) | LOG_EVENT_IGNORABLE_F);
7869 /* Recalc event's CRC */
7870 ha_checksum ev_crc = checksum_crc32(0L, nullptr, 0);
7871 ev_crc = checksum_crc32(ev_crc, (const uchar *)ev_buf,
7872 event_len - BINLOG_CHECKSUM_LEN);
7873 int4store(&ev_buf[event_len - BINLOG_CHECKSUM_LEN], ev_crc);
7874 /*
7875 We will skip writing this event to the relay log in order to let
7876 the startup procedure to not finding it and assuming this transaction
7877 is incomplete.
7878 But we have to keep the unknown ignorable error to let the
7879 "stop_io_after_reading_unknown_event" debug point to work after
7880 "queuing" this event.
7881 */
7882 mysql_mutex_lock(&mi->data_lock);
7883 mi->set_master_log_pos(mi->get_master_log_pos() + event_len);
7884 lock_count = 2;
7885 goto end;
7886 });
7887
7888 /*
7889 This transaction parser is used to ensure that the GTID of the transaction
7890 (if it has one) will only be added to the Retrieved_Gtid_Set after the
7891 last event of the transaction be queued.
7892 It will also be used to avoid rotating the relay log in the middle of
7893 a transaction.
7894 */
7895
1/2
✓ Branch 0 taken 1566456 times.
✗ Branch 1 not taken.
1566456 std::tie(info_error, log_event_info) = extract_log_event_basic_info(
7896 3132912 buf, event_len, mi->get_mi_description_event());
7897
6/8
✓ Branch 0 taken 1566456 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1566456 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 19 times.
✓ Branch 5 taken 1566437 times.
✓ Branch 6 taken 19 times.
✓ Branch 7 taken 1566437 times.
1566456 if (info_error || mi->transaction_parser.feed_event(log_event_info, true)) {
7898 /*
7899 The transaction parser detected a problem while changing state and threw
7900 a warning message. We are taking care of avoiding transaction boundary
7901 issues, but it can happen.
7902
7903 Transaction boundary errors might happen mostly because of bad master
7904 positioning in 'CHANGE MASTER TO' (or bad manipulation of master.info)
7905 when GTID auto positioning is off. Errors can also happen when using
7906 cross-version replication, replicating from a master that supports more
7907 event types than this slave.
7908
7909 The IO thread will keep working and queuing events regardless of the
7910 transaction parser error, but we will throw another warning message to
7911 log the relay log file and position of the parser error to help
7912 forensics.
7913 */
7914
8/16
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 19 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 19 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 19 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 19 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 19 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 19 times.
✗ Branch 15 not taken.
19 LogErr(WARNING_LEVEL,
7915 ER_RPL_SLAVE_IO_THREAD_DETECTED_UNEXPECTED_EVENT_SEQUENCE,
7916 mi->get_master_log_name(), mi->get_master_log_pos());
7917 }
7918
7919
3/4
✓ Branch 0 taken 1566456 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 285544 times.
✓ Branch 3 taken 1280912 times.
1566456 if (rli->is_row_format_required()) {
7920
3/4
✓ Branch 0 taken 285544 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 285537 times.
571088 if (info_error ||
7921
3/4
✓ Branch 0 taken 285544 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 285537 times.
285544 mi->transaction_parser.check_row_logging_constraints(log_event_info)) {
7922
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
14 mi->report(ERROR_LEVEL,
7923 ER_RPL_SLAVE_QUEUE_EVENT_FAILED_INVALID_NON_ROW_FORMAT,
7924
2/4
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
7 ER_THD(current_thd,
7925 ER_RPL_SLAVE_QUEUE_EVENT_FAILED_INVALID_NON_ROW_FORMAT),
7926 mi->get_channel());
7927 7 goto err;
7928 }
7929 }
7930
7931
10/10
✓ Branch 0 taken 137 times.
✓ Branch 1 taken 18413 times.
✓ Branch 2 taken 12671 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 2092 times.
✓ Branch 5 taken 10762 times.
✓ Branch 6 taken 19 times.
✓ Branch 7 taken 59168 times.
✓ Branch 8 taken 225017 times.
✓ Branch 9 taken 1238169 times.
1566449 switch (event_type) {
7932 137 case binary_log::STOP_EVENT:
7933 /*
7934 We needn't write this event to the relay log. Indeed, it just indicates
7935 a master server shutdown. The only thing this does is cleaning. But
7936 cleaning is already done on a per-master-thread basis (as the master
7937 server is shutting down cleanly, it has written all DROP TEMPORARY TABLE
7938 prepared statements' deletion are TODO only when we binlog prep stmts).
7939
7940 We don't even increment mi->get_master_log_pos(), because we may be just
7941 after a Rotate event. Btw, in a few milliseconds we are going to have a
7942 Start event from the next binlog (unless the master is presently running
7943 without --log-bin).
7944 */
7945 137 do_flush_mi = false;
7946 137 goto end;
7947 18413 case binary_log::ROTATE_EVENT: {
7948 18413 Format_description_log_event *fde = mi->get_mi_description_event();
7949 18413 enum_binlog_checksum_alg fde_checksum_alg = fde->footer()->checksum_alg;
7950
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 18409 times.
18413 if (fde_checksum_alg != checksum_alg)
7951 4 fde->footer()->checksum_alg = checksum_alg;
7952
1/2
✓ Branch 0 taken 18413 times.
✗ Branch 1 not taken.
18413 Rotate_log_event rev(buf, fde);
7953 18413 fde->footer()->checksum_alg = fde_checksum_alg;
7954
7955
3/4
✓ Branch 0 taken 18413 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 18409 times.
18413 if (unlikely(process_io_rotate(mi, &rev))) {
7956 // This error will be reported later at handle_slave_io().
7957 4 goto err;
7958 }
7959 /*
7960 Checksum special cases for the fake Rotate (R_f) event caused by the
7961 protocol of events generation and serialization in RL where Rotate of
7962 master is queued right next to FD of slave. Since it's only FD that
7963 carries the alg desc of FD_s has to apply to R_m. Two special rules
7964 apply only to the first R_f which comes in before any FD_m. The 2nd R_f
7965 should be compatible with the FD_s that must have taken over the last
7966 seen FD_m's (A).
7967
7968 RSC_1: If OM \and fake Rotate \and slave is configured to
7969 to compute checksum for its first FD event for RL
7970 the fake Rotate gets checksummed here.
7971 */
7972
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 12685 times.
31116 if (uint4korr(&buf[0]) == 0 &&
7973
4/4
✓ Branch 0 taken 12707 times.
✓ Branch 1 taken 5702 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 18406 times.
31116 checksum_alg == binary_log::BINLOG_CHECKSUM_ALG_OFF &&
7974
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 19 times.
22 mi->rli->relay_log.relay_log_checksum_alg !=
7975 binary_log::BINLOG_CHECKSUM_ALG_OFF) {
7976
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 ha_checksum rot_crc = checksum_crc32(0L, nullptr, 0);
7977 3 event_len += BINLOG_CHECKSUM_LEN;
7978 3 memcpy(rot_buf, buf, event_len - BINLOG_CHECKSUM_LEN);
7979 3 int4store(&rot_buf[EVENT_LEN_OFFSET],
7980 3 uint4korr(rot_buf + EVENT_LEN_OFFSET) + BINLOG_CHECKSUM_LEN);
7981
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 rot_crc = checksum_crc32(rot_crc, (const uchar *)rot_buf,
7982 event_len - BINLOG_CHECKSUM_LEN);
7983 3 int4store(&rot_buf[event_len - BINLOG_CHECKSUM_LEN], rot_crc);
7984
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 assert(event_len == uint4korr(&rot_buf[EVENT_LEN_OFFSET]));
7985
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 assert(mi->get_mi_description_event()->common_footer->checksum_alg ==
7986 mi->rli->relay_log.relay_log_checksum_alg);
7987 /* the first one */
7988
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 assert(mi->checksum_alg_before_fd !=
7989 binary_log::BINLOG_CHECKSUM_ALG_UNDEF);
7990 3 save_buf = buf;
7991 3 buf = rot_buf;
7992 } else
7993 /*
7994 RSC_2: If NM \and fake Rotate \and slave does not compute checksum
7995 the fake Rotate's checksum is stripped off before relay-logging.
7996 */
7997
2/2
✓ Branch 0 taken 12685 times.
✓ Branch 1 taken 19 times.
31110 if (uint4korr(&buf[0]) == 0 &&
7998
4/4
✓ Branch 0 taken 12704 times.
✓ Branch 1 taken 5702 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 18405 times.
31110 checksum_alg != binary_log::BINLOG_CHECKSUM_ALG_OFF &&
7999
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 12684 times.
12685 mi->rli->relay_log.relay_log_checksum_alg ==
8000 binary_log::BINLOG_CHECKSUM_ALG_OFF) {
8001 1 event_len -= BINLOG_CHECKSUM_LEN;
8002 1 memcpy(rot_buf, buf, event_len);
8003 1 int4store(&rot_buf[EVENT_LEN_OFFSET],
8004 1 uint4korr(rot_buf + EVENT_LEN_OFFSET) - BINLOG_CHECKSUM_LEN);
8005
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 assert(event_len == uint4korr(&rot_buf[EVENT_LEN_OFFSET]));
8006
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 assert(mi->get_mi_description_event()->common_footer->checksum_alg ==
8007 mi->rli->relay_log.relay_log_checksum_alg);
8008 /* the first one */
8009
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 assert(mi->checksum_alg_before_fd !=
8010 binary_log::BINLOG_CHECKSUM_ALG_UNDEF);
8011 1 save_buf = buf;
8012 1 buf = rot_buf;
8013 }
8014 /*
8015 Now the I/O thread has just changed its mi->get_master_log_name(), so
8016 incrementing mi->get_master_log_pos() is nonsense.
8017 */
8018 18409 inc_pos = 0;
8019 18409 break;
8020
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 18409 times.
18413 }
8021 12671 case binary_log::FORMAT_DESCRIPTION_EVENT: {
8022 /*
8023 Create an event, and save it (when we rotate the relay log, we will have
8024 to write this event again).
8025 */
8026 /*
8027 We are the only thread which reads/writes mi_description_event.
8028 The relay_log struct does not move (though some members of it can
8029 change), so we needn't any lock (no rli->data_lock, no log lock).
8030 */
8031 // mark it as undefined that is irrelevant anymore
8032 12671 mi->checksum_alg_before_fd = binary_log::BINLOG_CHECKSUM_ALG_UNDEF;
8033 Format_description_log_event *new_fdle;
8034 12671 Log_event *ev = nullptr;
8035
1/2
✓ Branch 0 taken 12671 times.
✗ Branch 1 not taken.
12671 if (binlog_event_deserialize(reinterpret_cast<const unsigned char *>(buf),
8036 12671 event_len, mi->get_mi_description_event(),
8037
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12671 times.
12671 true, &ev) != Binlog_read_error::SUCCESS) {
8038 // This error will be reported later at handle_slave_io().
8039 goto err;
8040 }
8041
8042
1/2
✓ Branch 0 taken 12671 times.
✗ Branch 1 not taken.
12671 new_fdle = dynamic_cast<Format_description_log_event *>(ev);
8043
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 12667 times.
12671 if (new_fdle->common_footer->checksum_alg ==
8044 binary_log::BINLOG_CHECKSUM_ALG_UNDEF)
8045 4 new_fdle->common_footer->checksum_alg =
8046 binary_log::BINLOG_CHECKSUM_ALG_OFF;
8047
8048
1/2
✓ Branch 0 taken 12671 times.
✗ Branch 1 not taken.
12671 mi->set_mi_description_event(new_fdle);
8049
8050 /* installing new value of checksum Alg for relay log */
8051 12671 mi->rli->relay_log.relay_log_checksum_alg =
8052 12671 new_fdle->common_footer->checksum_alg;
8053
8054 /*
8055 Though this does some conversion to the slave's format, this will
8056 preserve the master's binlog format version, and number of event types.
8057 */
8058 /*
8059 If the event was not requested by the slave (the slave did not ask for
8060 it), i.e. has end_log_pos=0, we do not increment
8061 mi->get_master_log_pos()
8062 */
8063
2/2
✓ Branch 0 taken 10764 times.
✓ Branch 1 taken 1907 times.
12671 inc_pos = uint4korr(buf + LOG_POS_OFFSET) ? event_len : 0;
8064
3/8
✓ Branch 0 taken 12671 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12671 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 12671 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
12671 DBUG_PRINT("info", ("binlog format is now %d",
8065 mi->get_mi_description_event()->binlog_version));
8066
8067 12671 } break;
8068
8069 1 case binary_log::HEARTBEAT_LOG_EVENT: {
8070 /*
8071 HB (heartbeat) cannot come before RL (Relay)
8072 */
8073
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 Heartbeat_log_event hb(buf, mi->get_mi_description_event());
8074 1 std::string mi_log_filename{mi->get_master_log_name() != nullptr
8075 1 ? mi->get_master_log_name()
8076
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 : ""};
8077
3/6
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
1 if (heartbeat_queue_event(hb.is_valid(), mi, mi_log_filename,
8078
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 hb.header()->log_pos, inc_pos, do_flush_mi))
8079 goto err;
8080 else
8081 1 goto end;
8082
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
2 } break;
8083
8084 2092 case binary_log::HEARTBEAT_LOG_EVENT_V2: {
8085 /*
8086 HB (heartbeat) cannot come before RL (Relay)
8087 */
8088
1/2
✓ Branch 0 taken 2092 times.
✗ Branch 1 not taken.
2092 Heartbeat_log_event_v2 hb(buf, mi->get_mi_description_event());
8089
1/2
✓ Branch 0 taken 2092 times.
✗ Branch 1 not taken.
2092 auto hb_log_filename = hb.get_log_filename();
8090
2/4
✓ Branch 0 taken 2092 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2092 times.
2092 auto hb_log_position = hb.get_log_position() == 0 ? hb.header()->log_pos
8091
1/2
✓ Branch 0 taken 2092 times.
✗ Branch 1 not taken.
2092 : hb.get_log_position();
8092 2092 std::string mi_log_filename{mi->get_master_log_name() != nullptr
8093 2092 ? mi->get_master_log_name()
8094
2/4
✓ Branch 0 taken 2092 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2092 times.
✗ Branch 3 not taken.
4184 : ""};
8095
4/8
✓ Branch 0 taken 2092 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2092 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2092 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 2092 times.
2092 if (heartbeat_queue_event(hb.is_valid(), mi, mi_log_filename,
8096 hb_log_position, inc_pos, do_flush_mi))
8097 goto err;
8098 else
8099 2092 goto end;
8100
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 2092 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2092 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2092 times.
6276 } break;
8101 10762 case binary_log::PREVIOUS_GTIDS_LOG_EVENT: {
8102 /*
8103 This event does not have any meaning for the slave and
8104 was just sent to show the slave the master is making
8105 progress and avoid possible deadlocks.
8106 So at this point, the event is replaced by a rotate
8107 event what will make the slave to update what it knows
8108 about the master's coordinates.
8109 */
8110 10762 inc_pos = 0;
8111
1/2
✓ Branch 0 taken 10762 times.
✗ Branch 1 not taken.
10762 mysql_mutex_lock(&mi->data_lock);
8112 10762 mi->set_master_log_pos(mi->get_master_log_pos() + event_len);
8113
1/2
✓ Branch 0 taken 10762 times.
✗ Branch 1 not taken.
10762 mysql_mutex_unlock(&mi->data_lock);
8114
8115
2/4
✓ Branch 0 taken 10762 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10762 times.
10762 if (write_rotate_to_master_pos_into_relay_log(
8116 mi->info_thd, mi, true /* force_flush_mi_info */))
8117 goto err;
8118
8119 10762 do_flush_mi = false; /* write_rotate_... above flushed master info */
8120 10762 goto end;
8121 } break;
8122
8123 19 case binary_log::TRANSACTION_PAYLOAD_EVENT: {
8124 binary_log::Transaction_payload_event tpe(buf,
8125
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 mi->get_mi_description_event());
8126 19 compression_type = tpe.get_compression_type();
8127 19 compressed_transaction_bytes = tpe.get_payload_size();
8128 19 uncompressed_transaction_bytes = tpe.get_uncompressed_size();
8129 19 auto gtid_monitoring_info = mi->get_gtid_monitoring_info();
8130
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 gtid_monitoring_info->update(compression_type,
8131 compressed_transaction_bytes,
8132 uncompressed_transaction_bytes);
8133 19 inc_pos = event_len;
8134 19 break;
8135 19 }
8136
8137 59168 case binary_log::GTID_LOG_EVENT: {
8138 /*
8139 This can happen if the master uses GTID_MODE=OFF_PERMISSIVE, and
8140 sends GTID events to the slave. A possible scenario is that user
8141 does not follow the upgrade procedure for GTIDs, and creates a
8142 topology like A->B->C, where A uses GTID_MODE=ON_PERMISSIVE, B
8143 uses GTID_MODE=OFF_PERMISSIVE, and C uses GTID_MODE=OFF. Each
8144 connection is allowed, but the master A will generate GTID
8145 transactions which will be sent through B to C. Then C will hit
8146 this error.
8147 */
8148
3/4
✓ Branch 0 taken 59168 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 59165 times.
59168 if (global_gtid_mode.get() == Gtid_mode::OFF) {
8149
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
6 mi->report(
8150 ERROR_LEVEL, ER_CANT_REPLICATE_GTID_WITH_GTID_MODE_OFF,
8151
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 ER_THD(current_thd, ER_CANT_REPLICATE_GTID_WITH_GTID_MODE_OFF),
8152 mi->get_master_log_name(), mi->get_master_log_pos());
8153 3 goto err;
8154 }
8155
1/2
✓ Branch 0 taken 59165 times.
✗ Branch 1 not taken.
59165 Gtid_log_event gtid_ev(buf, mi->get_mi_description_event());
8156
2/4
✓ Branch 0 taken 59165 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 59165 times.
59165 if (!gtid_ev.is_valid()) goto err;
8157
1/2
✓ Branch 0 taken 59165 times.
✗ Branch 1 not taken.
59165 rli->get_sid_lock()->rdlock();
8158
1/2
✓ Branch 0 taken 59165 times.
✗ Branch 1 not taken.
59165 gtid.sidno = gtid_ev.get_sidno(rli->get_gtid_set()->get_sid_map());
8159
1/2
✓ Branch 0 taken 59165 times.
✗ Branch 1 not taken.
59165 rli->get_sid_lock()->unlock();
8160
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59165 times.
59165 if (gtid.sidno < 0) goto err;
8161 59165 gtid.gno = gtid_ev.get_gno();
8162 59165 original_commit_timestamp = gtid_ev.original_commit_timestamp;
8163 59165 immediate_commit_timestamp = gtid_ev.immediate_commit_timestamp;
8164 59165 compressed_transaction_bytes = uncompressed_transaction_bytes =
8165
1/2
✓ Branch 0 taken 59165 times.
✗ Branch 1 not taken.
59165 gtid_ev.transaction_length - gtid_ev.get_event_length();
8166
8167 59165 inc_pos = event_len;
8168
1/2
✓ Branch 0 taken 59165 times.
✗ Branch 1 not taken.
118330 } break;
8169
8170 225017 case binary_log::ANONYMOUS_GTID_LOG_EVENT: {
8171 /*
8172 This cannot normally happen, because the master has a check that
8173 prevents it from sending anonymous events when auto_position is
8174 enabled. However, the master could be something else than
8175 mysqld, which could contain bugs that we have no control over.
8176 So we need this check on the slave to be sure that whoever is on
8177 the other side of the protocol does not break the protocol.
8178 */
8179
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 225014 times.
225017 if (mi->is_auto_position()) {
8180
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
6 mi->report(
8181 ERROR_LEVEL, ER_CANT_REPLICATE_ANONYMOUS_WITH_AUTO_POSITION,
8182
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 ER_THD(current_thd, ER_CANT_REPLICATE_ANONYMOUS_WITH_AUTO_POSITION),
8183 mi->get_master_log_name(), mi->get_master_log_pos());
8184 6 goto err;
8185 }
8186 /*
8187 This can happen if the master uses GTID_MODE=ON_PERMISSIVE, and
8188 sends an anonymous event to the slave. A possible scenario is
8189 that user does not follow the upgrade procedure for GTIDs, and
8190 creates a topology like A->B->C, where A uses
8191 GTID_MODE=OFF_PERMISSIVE, B uses GTID_MODE=ON_PERMISSIVE, and C
8192 uses GTID_MODE=ON. Each connection is allowed, but the master A
8193 will generate anonymous transactions which will be sent through
8194 B to C. Then C will hit this error.
8195 There is a special case where on the slave
8196 ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS= LOCAL/UUID in that case it is
8197 possible to replicate from a GTID_MODE=OFF master to a GTID_MODE=ON
8198 slave
8199 */
8200 450028 else if (mi->rli->m_assign_gtids_to_anonymous_transactions_info
8201
3/4
✓ Branch 0 taken 225014 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 224380 times.
✓ Branch 3 taken 634 times.
225014 .get_type() == Assign_gtids_to_anonymous_transactions_info::
8202 enum_type::AGAT_OFF) {
8203
3/4
✓ Branch 0 taken 224380 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 224377 times.
224380 if (global_gtid_mode.get() == Gtid_mode::ON) {
8204
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
6 mi->report(ERROR_LEVEL, ER_CANT_REPLICATE_ANONYMOUS_WITH_GTID_MODE_ON,
8205
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 ER_THD(current_thd,
8206 ER_CANT_REPLICATE_ANONYMOUS_WITH_GTID_MODE_ON),
8207 mi->get_master_log_name(), mi->get_master_log_pos());
8208 3 goto err;
8209 }
8210 }
8211 /*
8212 save the original_commit_timestamp and the immediate_commit_timestamp to
8213 be later used for monitoring
8214 */
8215
1/2
✓ Branch 0 taken 225011 times.
✗ Branch 1 not taken.
225011 Gtid_log_event anon_gtid_ev(buf, mi->get_mi_description_event());
8216 225011 original_commit_timestamp = anon_gtid_ev.original_commit_timestamp;
8217 225011 immediate_commit_timestamp = anon_gtid_ev.immediate_commit_timestamp;
8218 225011 compressed_transaction_bytes = uncompressed_transaction_bytes =
8219
1/2
✓ Branch 0 taken 225011 times.
✗ Branch 1 not taken.
225011 anon_gtid_ev.transaction_length - anon_gtid_ev.get_event_length();
8220 225011 }
8221 [[fallthrough]];
8222 default:
8223 1463180 inc_pos = event_len;
8224 1463180 break;
8225 }
8226
8227 /*
8228 Simulate an unknown ignorable log event by rewriting the write_rows log
8229 event and previous_gtids log event before writing them in relay log.
8230 */
8231
6/8
✓ Branch 0 taken 1553444 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 1553436 times.
✓ Branch 4 taken 7 times.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 7 times.
1553444 DBUG_EXECUTE_IF(
8232 "simulate_unknown_ignorable_log_event",
8233 if (event_type == binary_log::WRITE_ROWS_EVENT ||
8234 event_type == binary_log::PREVIOUS_GTIDS_LOG_EVENT) {
8235 uchar *event_buf =
8236 const_cast<uchar *>(reinterpret_cast<const uchar *>(buf));
8237 /* Overwrite the log event type with an unknown type. */
8238 event_buf[EVENT_TYPE_OFFSET] = binary_log::ENUM_END_EVENT + 1;
8239 /* Set LOG_EVENT_IGNORABLE_F for the log event. */
8240 int2store(event_buf + FLAGS_OFFSET,
8241 uint2korr(event_buf + FLAGS_OFFSET) | LOG_EVENT_IGNORABLE_F);
8242 });
8243
8244 /*
8245 If this event is originating from this server, don't queue it.
8246 We don't check this for 3.23 events because it's simpler like this; 3.23
8247 will be filtered anyway by the SQL slave thread which also tests the
8248 server id (we must also keep this test in the SQL thread, in case somebody
8249 upgrades a 4.0 slave which has a not-filtered relay log).
8250
8251 ANY event coming from ourselves can be ignored: it is obvious for queries;
8252 for STOP_EVENT/ROTATE_EVENT/START_EVENT: these cannot come from ourselves
8253 (--log-replica-updates would not log that) unless this slave is also its
8254 direct master (an unsupported, useless setup!).
8255 */
8256
8257 1553444 s_id = uint4korr(buf + SERVER_ID_OFFSET);
8258
8259 /*
8260 If server_id_bits option is set we need to mask out irrelevant bits
8261 when checking server_id, but we still put the full unmasked server_id
8262 into the Relay log so that it can be accessed when applying the event
8263 */
8264 1553444 s_id &= opt_server_id_mask;
8265
8266
6/6
✓ Branch 0 taken 23948 times.
✓ Branch 1 taken 1529496 times.
✓ Branch 2 taken 15474 times.
✓ Branch 3 taken 8474 times.
✓ Branch 4 taken 8492 times.
✓ Branch 5 taken 1544952 times.
3098414 if ((s_id == ::server_id && !mi->rli->replicate_same_server_id) ||
8267 /*
8268 the following conjunction deals with IGNORE_SERVER_IDS, if set
8269 If the master is on the ignore list, execution of
8270 format description log events and rotate events is necessary.
8271 */
8272
3/4
✓ Branch 0 taken 1544970 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 44 times.
✓ Branch 3 taken 1544926 times.
1544970 (mi->ignore_server_ids->dynamic_ids.size() > 0 &&
8273
3/4
✓ Branch 0 taken 44 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 30 times.
✓ Branch 3 taken 14 times.
44 mi->shall_ignore_server_id(s_id) &&
8274 /* everything is filtered out from non-master */
8275
3/4
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
✓ Branch 3 taken 6 times.
30 (s_id != mi->master_id ||
8276 /* for the master meta information is necessary */
8277
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 6 times.
24 (event_type != binary_log::FORMAT_DESCRIPTION_EVENT &&
8278 event_type != binary_log::ROTATE_EVENT)))) {
8279 /*
8280 Do not write it to the relay log.
8281 a) We still want to increment mi->get_master_log_pos(), so that we won't
8282 re-read this event from the master if the slave IO thread is now
8283 stopped/restarted (more efficient if the events we are ignoring are big
8284 LOAD DATA INFILE).
8285 b) We want to record that we are skipping events, for the information of
8286 the slave SQL thread, otherwise that thread may let
8287 rli->group_relay_log_pos stay too small if the last binlog's event is
8288 ignored.
8289 But events which were generated by this slave and which do not exist in
8290 the master's binlog (i.e. Format_desc, Rotate & Stop) should not increment
8291 mi->get_master_log_pos().
8292 If the event is originated remotely and is being filtered out by
8293 IGNORE_SERVER_IDS it increments mi->get_master_log_pos()
8294 as well as rli->group_relay_log_pos.
8295 */
8296
4/6
✓ Branch 0 taken 8474 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 8474 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8474 times.
✗ Branch 5 not taken.
8492 if (!(s_id == ::server_id && !mi->rli->replicate_same_server_id) ||
8297
1/2
✓ Branch 0 taken 8474 times.
✗ Branch 1 not taken.
8474 (event_type != binary_log::FORMAT_DESCRIPTION_EVENT &&
8298
1/2
✓ Branch 0 taken 8474 times.
✗ Branch 1 not taken.
8474 event_type != binary_log::ROTATE_EVENT &&
8299 event_type != binary_log::STOP_EVENT)) {
8300
1/2
✓ Branch 0 taken 8492 times.
✗ Branch 1 not taken.
8492 rli->relay_log.lock_binlog_end_pos();
8301 8492 mi->set_master_log_pos(mi->get_master_log_pos() + inc_pos);
8302 8492 memcpy(rli->ign_master_log_name_end, mi->get_master_log_name(),
8303 FN_REFLEN);
8304
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8492 times.
8492 assert(rli->ign_master_log_name_end[0]);
8305 8492 rli->ign_master_log_pos_end = mi->get_master_log_pos();
8306 // the slave SQL thread needs to re-check
8307
1/2
✓ Branch 0 taken 8492 times.
✗ Branch 1 not taken.
8492 rli->relay_log.update_binlog_end_pos(false /*need_lock*/);
8308
1/2
✓ Branch 0 taken 8492 times.
✗ Branch 1 not taken.
8492 rli->relay_log.unlock_binlog_end_pos();
8309 }
8310
3/8
✓ Branch 0 taken 8492 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8492 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 8492 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
8492 DBUG_PRINT(
8311 "info",
8312 ("master_log_pos: %lu, event originating from %u server, ignored",
8313 (ulong)mi->get_master_log_pos(), uint4korr(buf + SERVER_ID_OFFSET)));
8314 } else {
8315 1544952 bool is_error = false;
8316 /* write the event to the relay log */
8317
3/4
✓ Branch 0 taken 1544952 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1544946 times.
✓ Branch 3 taken 6 times.
1544952 if (likely(rli->relay_log.write_buffer(
8318 reinterpret_cast<uchar *>(const_cast<char *>(buf)),
8319 event_len, mi) == 0)) {
8320
6/10
✓ Branch 0 taken 1544946 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 1544940 times.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 6 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 6 times.
1544946 DBUG_SIGNAL_WAIT_FOR(current_thd,
8321 "pause_on_queue_event_after_write_buffer",
8322 "receiver_reached_pause_on_queue_event",
8323 "receiver_continue_queuing_event");
8324
1/2
✓ Branch 0 taken 1544946 times.
✗ Branch 1 not taken.
1544946 mysql_mutex_lock(&mi->data_lock);
8325 1544946 lock_count = 2;
8326 1544946 mi->set_master_log_pos(mi->get_master_log_pos() + inc_pos);
8327
3/8
✓ Branch 0 taken 1544946 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1544946 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1544946 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
1544946 DBUG_PRINT("info",
8328 ("master_log_pos: %lu", (ulong)mi->get_master_log_pos()));
8329
8330 /*
8331 If we are starting an anonymous transaction, we will discard
8332 the GTID of the partial transaction that was not finished (if
8333 there is one) when calling mi->started_queueing().
8334 */
8335 #ifndef NDEBUG
8336
2/2
✓ Branch 0 taken 223523 times.
✓ Branch 1 taken 1321423 times.
1544946 if (event_type == binary_log::ANONYMOUS_GTID_LOG_EVENT) {
8337
3/4
✓ Branch 0 taken 223523 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 223522 times.
223523 if (!mi->get_queueing_trx_gtid()->is_empty()) {
8338
3/12
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
1 DBUG_PRINT("info",
8339 ("Discarding Gtid(%d, %" PRId64 ") as the transaction "
8340 "wasn't complete and we found an "
8341 "ANONYMOUS_GTID_LOG_EVENT.",
8342 mi->get_queueing_trx_gtid()->sidno,
8343 mi->get_queueing_trx_gtid()->gno));
8344 }
8345 }
8346 #endif
8347
8348 /*
8349 We have to mark this GTID (either anonymous or not) as started
8350 to be queued.
8351
8352 Also, if this event is a GTID_LOG_EVENT, we have to store its GTID to
8353 add to the Retrieved_Gtid_Set later, when the last event of the
8354 transaction be queued. The call to mi->started_queueing() will save
8355 the GTID to be used later.
8356 */
8357
4/4
✓ Branch 0 taken 1485813 times.
✓ Branch 1 taken 59133 times.
✓ Branch 2 taken 223523 times.
✓ Branch 3 taken 1262290 times.
1544946 if (event_type == binary_log::GTID_LOG_EVENT ||
8358 event_type == binary_log::ANONYMOUS_GTID_LOG_EVENT) {
8359 // set the timestamp for the start time of queueing this transaction
8360
1/2
✓ Branch 0 taken 282656 times.
✗ Branch 1 not taken.
282656 mi->started_queueing(gtid, original_commit_timestamp,
8361 immediate_commit_timestamp);
8362
8363 282656 auto gtid_monitoring_info = mi->get_gtid_monitoring_info();
8364
1/2
✓ Branch 0 taken 282656 times.
✗ Branch 1 not taken.
282656 gtid_monitoring_info->update(
8365 binary_log::transaction::compression::type::NONE,
8366 compressed_transaction_bytes, uncompressed_transaction_bytes);
8367 }
8368 } else {
8369 /*
8370 We failed to write the event and didn't updated slave positions.
8371
8372 We have to "rollback" the transaction parser state, or else, when
8373 restarting the I/O thread without GTID auto positing the parser
8374 would assume the failed event as queued.
8375 */
8376 6 mi->transaction_parser.rollback();
8377 6 is_error = true;
8378 }
8379
8380
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1544948 times.
1544952 if (save_buf != nullptr) buf = save_buf;
8381
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1544946 times.
1544952 if (is_error) {
8382 // This error will be reported later at handle_slave_io().
8383 6 goto err;
8384 }
8385 }
8386 1553438 goto end;
8387
8388 33 err:
8389 33 res = QUEUE_EVENT_ERROR_QUEUING;
8390
8391 1566465 end:
8392
4/4
✓ Branch 0 taken 1566432 times.
✓ Branch 1 taken 33 times.
✓ Branch 2 taken 1330730 times.
✓ Branch 3 taken 235702 times.
1566465 if (res == QUEUE_EVENT_OK && do_flush_mi) {
8393 /*
8394 Take a ride in the already locked LOCK_log to flush master info.
8395
8396 JAG: TODO: Notice that we could only flush master info if we are
8397 not in the middle of a transaction. Having a proper
8398 relay log recovery can allow us to do this.
8399 */
8400
2/2
✓ Branch 0 taken 9684 times.
✓ Branch 1 taken 1321046 times.
1330730 if (lock_count == 1) {
8401
1/2
✓ Branch 0 taken 9684 times.
✗ Branch 1 not taken.
9684 mysql_mutex_lock(&mi->data_lock);
8402 9684 lock_count = 2;
8403 }
8404
8405
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1330730 times.
1330730 if (flush_master_info(mi, false /*force*/, lock_count == 0 /*need_lock*/,
8406
2/4
✓ Branch 0 taken 1330730 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1330730 times.
✗ Branch 3 not taken.
1330730 false /*flush_relay_log*/, mi->is_gtid_only_mode()))
8407 res = QUEUE_EVENT_ERROR_FLUSHING_INFO;
8408
3/4
✓ Branch 0 taken 1330730 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 59673 times.
✓ Branch 3 taken 1271057 times.
1330730 if (mi->is_gtid_only_mode()) {
8409
1/2
✓ Branch 0 taken 59673 times.
✗ Branch 1 not taken.
59673 mi->update_flushed_relay_log_info();
8410 }
8411 }
8412
3/4
✓ Branch 0 taken 1554632 times.
✓ Branch 1 taken 11833 times.
✓ Branch 2 taken 1554632 times.
✗ Branch 3 not taken.
1566465 if (lock_count >= 2) mysql_mutex_unlock(&mi->data_lock);
8413
3/4
✓ Branch 0 taken 1566458 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 1566458 times.
✗ Branch 3 not taken.
1566465 if (lock_count >= 1) mysql_mutex_unlock(log_lock);
8414
3/8
✓ Branch 0 taken 1566465 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1566464 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1566464 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
1566465 DBUG_PRINT("info", ("queue result: %d", res));
8415 1566465 return res;
8416 1566464 }
8417
8418 /**
8419 Hook to detach the active VIO before closing a connection handle.
8420
8421 The client API might close the connection (and associated data)
8422 in case it encounters a unrecoverable (network) error. This hook
8423 is called from the client code before the VIO handle is deleted
8424 allows the thread to detach the active vio so it does not point
8425 to freed memory.
8426
8427 Other calls to THD::clear_active_vio throughout this module are
8428 redundant due to the hook but are left in place for illustrative
8429 purposes.
8430 */
8431
8432 10774 void slave_io_thread_detach_vio() {
8433 10774 THD *thd = current_thd;
8434
4/4
✓ Branch 0 taken 10262 times.
✓ Branch 1 taken 512 times.
✓ Branch 2 taken 7948 times.
✓ Branch 3 taken 2314 times.
10774 if (thd && thd->slave_thread) thd->clear_active_vio();
8435 10774 }
8436
8437 /*
8438 Set network namespace if channel is using network namespace and connect
8439 to master.
8440
8441 @param thd THD context
8442 @param mysql MYSQL connection handler
8443 @param mi Master info corresponding to this channel.
8444 @param reconnect Reconnect if true
8445 @param suppress_warnings suppress warnings if required.
8446
8447 @retval 0 ok.
8448 @retval 1 not ok.
8449 */
8450 7471 static int connect_to_master_via_namespace(THD *thd, MYSQL *mysql,
8451 Master_info *mi, bool reconnect,
8452 bool suppress_warnings,
8453 const std::string &host,
8454 const uint port) {
8455
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7471 times.
7471 if (mi->is_set_network_namespace()) {
8456 #ifdef HAVE_SETNS
8457 if (set_network_namespace(mi->network_namespace)) return 1;
8458 #else
8459 // Network namespace not supported by the platform. Report error.
8460 LogErr(ERROR_LEVEL, ER_NETWORK_NAMESPACES_NOT_SUPPORTED);
8461 return 1;
8462 #endif
8463 // Save default value of network namespace
8464 // Set network namespace before sockets be created
8465 }
8466 7471 int connect_res = connect_to_master(thd, mysql, mi, reconnect,
8467 suppress_warnings, host, port);
8468 // we can get killed during safe_connect
8469 #ifdef HAVE_SETNS
8470
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7471 times.
7471 if (mi->is_set_network_namespace()) {
8471 // Restore original network namespace used to be before connection has
8472 // been created
8473 (void)restore_original_network_namespace();
8474 }
8475 #endif
8476 7471 return connect_res;
8477 }
8478
8479 /*
8480 Try to connect until successful or slave killed
8481
8482 SYNPOSIS
8483 safe_connect()
8484 thd Thread handler for slave
8485 mysql MySQL connection handle
8486 mi Replication handle
8487
8488 RETURN
8489 0 ok
8490 # Error
8491 */
8492 7119 static int safe_connect(THD *thd, MYSQL *mysql, Master_info *mi,
8493 const std::string &host, const uint port) {
8494
1/2
✓ Branch 0 taken 7119 times.
✗ Branch 1 not taken.
7119 DBUG_TRACE;
8495
8496
1/2
✓ Branch 0 taken 7119 times.
✗ Branch 1 not taken.
7119 return connect_to_master_via_namespace(thd, mysql, mi,
8497 /*reconnect=*/false,
8498 /*suppress_warnings=*/false, host,
8499 14238 port);
8500 7119 }
8501
8502 7731 int connect_to_master(THD *thd, MYSQL *mysql, Master_info *mi, bool reconnect,
8503 bool suppress_warnings, const std::string &host,
8504 const uint port, bool is_io_thread) {
8505 7731 int last_errno = -2; // impossible error
8506 7731 ulong err_count = 0;
8507 char llbuff[22];
8508 char password[MAX_PASSWORD_LENGTH + 1];
8509 7731 size_t password_size = sizeof(password);
8510
1/2
✓ Branch 0 taken 7731 times.
✗ Branch 1 not taken.
7731 DBUG_TRACE;
8511
1/2
✓ Branch 0 taken 7731 times.
✗ Branch 1 not taken.
7731 set_replica_max_allowed_packet(thd, mysql);
8512 #ifndef NDEBUG
8513 7731 mi->events_until_exit = disconnect_slave_event_count;
8514 #endif
8515 7731 ulong client_flag = CLIENT_REMEMBER_OPTIONS;
8516
8517 /* Always reset public key to remove cached copy */
8518
1/2
✓ Branch 0 taken 7731 times.
✗ Branch 1 not taken.
7731 mysql_reset_server_public_key();
8519
8520
1/2
✓ Branch 0 taken 7731 times.
✗ Branch 1 not taken.
7731 mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, (char *)&replica_net_timeout);
8521
1/2
✓ Branch 0 taken 7731 times.
✗ Branch 1 not taken.
7731 mysql_options(mysql, MYSQL_OPT_READ_TIMEOUT, (char *)&replica_net_timeout);
8522
8523
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 7719 times.
7731 if (mi->bind_addr[0]) {
8524
3/8
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 12 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
12 DBUG_PRINT("info", ("bind_addr: %s", mi->bind_addr));
8525
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 mysql_options(mysql, MYSQL_OPT_BIND, mi->bind_addr);
8526 }
8527
8528 /* By default the channel is not configured to use SSL */
8529 7731 enum mysql_ssl_mode ssl_mode = SSL_MODE_DISABLED;
8530
2/2
✓ Branch 0 taken 144 times.
✓ Branch 1 taken 7587 times.
7731 if (mi->ssl) {
8531 /* The channel is configured to use SSL */
8532
3/4
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 103 times.
✓ Branch 2 taken 144 times.
✗ Branch 3 not taken.
576 mysql_ssl_set(mysql, mi->ssl_key[0] ? mi->ssl_key : nullptr,
8533
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 103 times.
144 mi->ssl_cert[0] ? mi->ssl_cert : nullptr,
8534
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 103 times.
144 mi->ssl_ca[0] ? mi->ssl_ca : nullptr,
8535
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
144 mi->ssl_capath[0] ? mi->ssl_capath : nullptr,
8536
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
144 mi->ssl_cipher[0] ? mi->ssl_cipher : nullptr);
8537
1/2
✓ Branch 0 taken 144 times.
✗ Branch 1 not taken.
144 mysql_options(mysql, MYSQL_OPT_SSL_CRL,
8538
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 140 times.
144 mi->ssl_crl[0] ? mi->ssl_crl : nullptr);
8539
1/2
✓ Branch 0 taken 144 times.
✗ Branch 1 not taken.
144 mysql_options(mysql, MYSQL_OPT_TLS_VERSION,
8540
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 113 times.
144 mi->tls_version[0] ? mi->tls_version : nullptr);
8541
1/2
✓ Branch 0 taken 144 times.
✗ Branch 1 not taken.
144 mysql_options(mysql, MYSQL_OPT_TLS_CIPHERSUITES,
8542
2/2
✓ Branch 0 taken 132 times.
✓ Branch 1 taken 12 times.
144 mi->tls_ciphersuites.first
8543 ? nullptr
8544 12 : mi->tls_ciphersuites.second.c_str());
8545
1/2
✓ Branch 0 taken 144 times.
✗ Branch 1 not taken.
144 mysql_options(mysql, MYSQL_OPT_SSL_CRLPATH,
8546
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 140 times.
144 mi->ssl_crlpath[0] ? mi->ssl_crlpath : nullptr);
8547
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 135 times.
144 if (mi->ssl_verify_server_cert)
8548 9 ssl_mode = SSL_MODE_VERIFY_IDENTITY;
8549
3/4
✓ Branch 0 taken 103 times.
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 103 times.
135 else if (mi->ssl_ca[0] || mi->ssl_capath[0])
8550 32 ssl_mode = SSL_MODE_VERIFY_CA;
8551 else
8552 103 ssl_mode = SSL_MODE_REQUIRED;
8553 }
8554
1/2
✓ Branch 0 taken 7731 times.
✗ Branch 1 not taken.
7731 mysql_options(mysql, MYSQL_OPT_SSL_MODE, &ssl_mode);
8555
8556
3/4
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 7708 times.
✓ Branch 2 taken 7731 times.
✗ Branch 3 not taken.
7731 mysql_options(mysql, MYSQL_OPT_COMPRESSION_ALGORITHMS,
8557 opt_replica_compressed_protocol ? COMPRESSION_ALGORITHM_ZLIB
8558 : mi->compression_algorithm);
8559 7731 mysql_options(mysql, MYSQL_OPT_ZSTD_COMPRESSION_LEVEL,
8560
1/2
✓ Branch 0 taken 7731 times.
✗ Branch 1 not taken.
7731 &mi->zstd_compression_level);
8561 /*
8562 If server's default charset is not supported (like utf16, utf32) as client
8563 charset, then set client charset to 'latin1' (default client charset).
8564 */
8565
2/2
✓ Branch 0 taken 7725 times.
✓ Branch 1 taken 6 times.
7731 if (is_supported_parser_charset(default_charset_info))
8566
1/2
✓ Branch 0 taken 7725 times.
✗ Branch 1 not taken.
7725 mysql_options(mysql, MYSQL_SET_CHARSET_NAME, default_charset_info->csname);
8567 else {
8568
8/16
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 6 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 6 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 6 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 6 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 6 times.
✗ Branch 15 not taken.
6 LogErr(INFORMATION_LEVEL, ER_RPL_SLAVE_CANT_USE_CHARSET,
8569 default_charset_info->csname, default_client_charset_info->csname);
8570 6 mysql_options(mysql, MYSQL_SET_CHARSET_NAME,
8571
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 default_client_charset_info->csname);
8572 }
8573
8574
2/2
✓ Branch 0 taken 61 times.
✓ Branch 1 taken 7670 times.
7731 if (mi->is_start_plugin_auth_configured()) {
8575
3/8
✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 61 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 61 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
61 DBUG_PRINT("info", ("Slaving is using MYSQL_DEFAULT_AUTH %s",
8576 mi->get_start_plugin_auth()));
8577
1/2
✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
61 mysql_options(mysql, MYSQL_DEFAULT_AUTH, mi->get_start_plugin_auth());
8578 }
8579
8580
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 7689 times.
7731 if (mi->is_start_plugin_dir_configured()) {
8581
3/8
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 42 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 42 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
42 DBUG_PRINT("info", ("Slaving is using MYSQL_PLUGIN_DIR %s",
8582 mi->get_start_plugin_dir()));
8583
1/2
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
42 mysql_options(mysql, MYSQL_PLUGIN_DIR, mi->get_start_plugin_dir());
8584 }
8585 /* Set MYSQL_PLUGIN_DIR in case master asks for an external authentication
8586 plugin */
8587
2/4
✓ Branch 0 taken 7689 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7689 times.
✗ Branch 3 not taken.
7689 else if (opt_plugin_dir_ptr && *opt_plugin_dir_ptr)
8588
1/2
✓ Branch 0 taken 7689 times.
✗ Branch 1 not taken.
7689 mysql_options(mysql, MYSQL_PLUGIN_DIR, opt_plugin_dir_ptr);
8589
8590
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 7717 times.
7731 if (mi->public_key_path[0]) {
8591 /* Set public key path */
8592
3/8
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 14 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
14 DBUG_PRINT("info", ("Set master's public key path"));
8593
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 mysql_options(mysql, MYSQL_SERVER_PUBLIC_KEY, mi->public_key_path);
8594 }
8595
8596 /* Get public key from master */
8597
3/8
✓ Branch 0 taken 7731 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7731 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 7731 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
7731 DBUG_PRINT("info", ("Set preference to get public key from master"));
8598
1/2
✓ Branch 0 taken 7731 times.
✗ Branch 1 not taken.
7731 mysql_options(mysql, MYSQL_OPT_GET_SERVER_PUBLIC_KEY, &mi->get_public_key);
8599
8600
6/6
✓ Branch 0 taken 7471 times.
✓ Branch 1 taken 260 times.
✓ Branch 2 taken 7318 times.
✓ Branch 3 taken 153 times.
✓ Branch 4 taken 7318 times.
✓ Branch 5 taken 413 times.
7731 if (is_io_thread && !mi->is_start_user_configured())
8601
8/16
✓ Branch 0 taken 7318 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7318 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7318 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 7318 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 7318 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 7318 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 7318 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 7318 times.
✗ Branch 15 not taken.
7318 LogErr(WARNING_LEVEL, ER_RPL_SLAVE_INSECURE_CHANGE_MASTER);
8602
8603
2/4
✓ Branch 0 taken 7731 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7731 times.
7731 if (mi->get_password(password, &password_size)) {
8604 mi->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
8605 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
8606 "Unable to configure password when attempting to "
8607 "connect to the master server. Connection attempt "
8608 "terminated.");
8609 return 1;
8610 }
8611
8612 7731 const char *user = mi->get_user();
8613
3/4
✓ Branch 0 taken 7731 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
✓ Branch 3 taken 7707 times.
7731 if (user == nullptr || user[0] == 0) {
8614
2/4
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
24 mi->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
8615 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
8616 "Invalid (empty) username when attempting to "
8617 "connect to the master server. Connection attempt "
8618 "terminated.");
8619 24 return 1;
8620 }
8621
8622
1/2
✓ Branch 0 taken 7707 times.
✗ Branch 1 not taken.
7707 mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, "program_name", "mysqld");
8623
1/2
✓ Branch 0 taken 7707 times.
✗ Branch 1 not taken.
7707 mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, "_client_role",
8624 "binary_log_listener");
8625
1/2
✓ Branch 0 taken 7707 times.
✗ Branch 1 not taken.
7707 mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD,
8626 7707 "_client_replication_channel_name", mi->get_channel());
8627
8628
2/2
✓ Branch 0 taken 7447 times.
✓ Branch 1 taken 260 times.
7707 const char *tmp_host = host.empty() ? mi->host : host.c_str();
8629
2/2
✓ Branch 0 taken 7447 times.
✓ Branch 1 taken 260 times.
7707 uint tmp_port = (port == 0) ? mi->port : port;
8630
8631 7707 bool replica_was_killed{false};
8632 7707 bool connected{false};
8633
8634
1/2
✓ Branch 0 taken 8141 times.
✗ Branch 1 not taken.
8141 while (!connected) {
8635
3/4
✓ Branch 0 taken 7842 times.
✓ Branch 1 taken 299 times.
✓ Branch 2 taken 7842 times.
✗ Branch 3 not taken.
8141 replica_was_killed = is_io_thread ? io_slave_killed(thd, mi)
8636
1/2
✓ Branch 0 taken 299 times.
✗ Branch 1 not taken.
299 : monitor_io_replica_killed(thd, mi);
8637
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 8108 times.
8141 if (replica_was_killed) break;
8638
8639
2/2
✓ Branch 0 taken 466 times.
✓ Branch 1 taken 7642 times.
8108 if (reconnect) {
8640
1/2
✓ Branch 0 taken 466 times.
✗ Branch 1 not taken.
466 connected = !mysql_reconnect(mysql);
8641 } else {
8642 // Set this each time mysql_real_connect() is called to make a connection
8643
1/2
✓ Branch 0 taken 7642 times.
✗ Branch 1 not taken.
7642 mysql_extension_set_server_extn(mysql, &mi->server_extn);
8644
8645
1/2
✓ Branch 0 taken 7642 times.
✗ Branch 1 not taken.
7642 connected = mysql_real_connect(mysql, tmp_host, user, password, nullptr,
8646 tmp_port, nullptr, client_flag);
8647 }
8648
2/2
✓ Branch 0 taken 7413 times.
✓ Branch 1 taken 695 times.
8108 if (connected) break;
8649
8650 /*
8651 SHOW REPLICA STATUS will display the number of retries which
8652 would be real retry counts instead of mi->retry_count for
8653 each connection attempt by 'Last_IO_Error' entry.
8654 */
8655
1/2
✓ Branch 0 taken 695 times.
✗ Branch 1 not taken.
695 last_errno = mysql_errno(mysql);
8656 695 suppress_warnings = false;
8657
2/2
✓ Branch 0 taken 591 times.
✓ Branch 1 taken 104 times.
695 if (is_io_thread) {
8658
4/6
✓ Branch 0 taken 591 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 170 times.
✓ Branch 3 taken 421 times.
✓ Branch 4 taken 591 times.
✗ Branch 5 not taken.
591 mi->report(ERROR_LEVEL, last_errno,
8659 "error %s to master '%s@%s:%d'"
8660 " - retry-time: %d retries: %lu message: %s",
8661 (reconnect ? "reconnecting" : "connecting"), mi->get_user(),
8662 tmp_host, tmp_port, mi->connect_retry, err_count + 1,
8663 mysql_error(mysql));
8664 }
8665
8666 /*
8667 By default we try forever. The reason is that failure will trigger
8668 master election, so if the user did not set mi->retry_count we
8669 do not want to have election triggered on the first failure to
8670 connect
8671 */
8672
2/2
✓ Branch 0 taken 261 times.
✓ Branch 1 taken 434 times.
695 if (++err_count == mi->retry_count) {
8673
7/8
✓ Branch 0 taken 261 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 151 times.
✓ Branch 3 taken 110 times.
✓ Branch 4 taken 87 times.
✓ Branch 5 taken 64 times.
✓ Branch 6 taken 87 times.
✓ Branch 7 taken 174 times.
261 if (is_network_error(last_errno) && is_io_thread) mi->set_network_error();
8674 261 replica_was_killed = true;
8675 261 break;
8676 }
8677
3/4
✓ Branch 0 taken 395 times.
✓ Branch 1 taken 39 times.
✓ Branch 2 taken 434 times.
✗ Branch 3 not taken.
434 slave_sleep(thd, mi->connect_retry,
8678 is_io_thread ? io_slave_killed : monitor_io_replica_killed, mi);
8679 }
8680
8681
2/2
✓ Branch 0 taken 7413 times.
✓ Branch 1 taken 294 times.
7707 if (!replica_was_killed) {
8682
2/2
✓ Branch 0 taken 7219 times.
✓ Branch 1 taken 194 times.
7413 if (is_io_thread) {
8683
1/2
✓ Branch 0 taken 7219 times.
✗ Branch 1 not taken.
7219 mi->clear_error(); // clear possible left over reconnect error
8684 7219 mi->reset_network_error();
8685 }
8686
8687
2/2
✓ Branch 0 taken 296 times.
✓ Branch 1 taken 7117 times.
7413 if (reconnect) {
8688
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 277 times.
296 if (!suppress_warnings)
8689
10/20
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 19 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 19 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 19 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 19 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 19 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 19 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 19 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 19 times.
✗ Branch 19 not taken.
19 LogErr(
8690 SYSTEM_LEVEL, ER_RPL_SLAVE_CONNECTED_TO_MASTER_REPLICATION_RESUMED,
8691 mi->get_for_channel_str(), mi->get_user(), tmp_host, tmp_port,
8692 mi->get_io_rpl_log_name(), llstr(mi->get_master_log_pos(), llbuff));
8693 } else {
8694
1/2
✓ Branch 0 taken 7117 times.
✗ Branch 1 not taken.
7117 query_logger.general_log_print(thd, COM_CONNECT_OUT, "%s@%s:%d",
8695 mi->get_user(), tmp_host, tmp_port);
8696 }
8697
8698
1/2
✓ Branch 0 taken 7413 times.
✗ Branch 1 not taken.
7413 thd->set_active_vio(mysql->net.vio);
8699 }
8700 7707 mysql->reconnect = true;
8701
3/8
✓ Branch 0 taken 7707 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7707 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 7707 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
7707 DBUG_PRINT("exit", ("replica_was_killed: %d", replica_was_killed));
8702 7707 return replica_was_killed;
8703 7731 }
8704
8705 /*
8706 safe_reconnect()
8707
8708 IMPLEMENTATION
8709 Try to connect until successful or slave killed or we have retried
8710 mi->retry_count times
8711 */
8712
8713 352 static int safe_reconnect(THD *thd, MYSQL *mysql, Master_info *mi,
8714 bool suppress_warnings, const std::string &host,
8715 const uint port) {
8716
1/2
✓ Branch 0 taken 352 times.
✗ Branch 1 not taken.
352 DBUG_TRACE;
8717
1/2
✓ Branch 0 taken 352 times.
✗ Branch 1 not taken.
352 return connect_to_master_via_namespace(thd, mysql, mi,
8718 /*reconnect=*/true, suppress_warnings,
8719 704 host, port);
8720 352 }
8721
8722 /*
8723 Rotate a relay log (this is used only by FLUSH LOGS; the automatic rotation
8724 because of size is simpler because when we do it we already have all relevant
8725 locks; here we don't, so this function is mainly taking locks).
8726 Returns nothing as we cannot catch any error (MYSQL_BIN_LOG::new_file()
8727 is void).
8728 */
8729
8730 23630 int rotate_relay_log(Master_info *mi, bool log_master_fd, bool need_lock,
8731 bool need_log_space_lock) {
8732
1/2
✓ Branch 0 taken 23630 times.
✗ Branch 1 not taken.
23630 DBUG_TRACE;
8733
8734 23630 Relay_log_info *rli = mi->rli;
8735
8736
2/2
✓ Branch 0 taken 5217 times.
✓ Branch 1 taken 18413 times.
23630 if (need_lock)
8737
1/2
✓ Branch 0 taken 5217 times.
✗ Branch 1 not taken.
5217 mysql_mutex_lock(rli->relay_log.get_log_lock());
8738 else
8739 mysql_mutex_assert_owner(rli->relay_log.get_log_lock());
8740
4/6
✓ Branch 0 taken 23630 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 23624 times.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
23630 DBUG_EXECUTE_IF("crash_before_rotate_relaylog", DBUG_SUICIDE(););
8741
8742 23624 int error = 0;
8743
8744 /*
8745 We need to test inited because otherwise, new_file() will attempt to lock
8746 LOCK_log, which may not be inited (if we're not a slave).
8747 */
8748
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23624 times.
23624 if (!rli->inited) {
8749 DBUG_PRINT("info", ("rli->inited == 0"));
8750 goto end;
8751 }
8752
8753 /* If the relay log is closed, new_file() will do nothing. */
8754
2/2
✓ Branch 0 taken 5211 times.
✓ Branch 1 taken 18413 times.
23624 if (log_master_fd)
8755 error =
8756
1/2
✓ Branch 0 taken 5211 times.
✗ Branch 1 not taken.
5211 rli->relay_log.new_file_without_locking(mi->get_mi_description_event());
8757 else
8758
1/2
✓ Branch 0 taken 18413 times.
✗ Branch 1 not taken.
18413 error = rli->relay_log.new_file_without_locking(nullptr);
8759
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 23620 times.
23624 if (error != 0) goto end;
8760
8761 /*
8762 We harvest now, because otherwise BIN_LOG_HEADER_SIZE will not immediately
8763 be counted, so imagine a succession of FLUSH LOGS and assume the slave
8764 threads are started:
8765 relay_log_space decreases by the size of the deleted relay log, but does
8766 not increase, so flush-after-flush we may become negative, which is wrong.
8767 Even if this will be corrected as soon as a query is replicated on the
8768 slave (because the I/O thread will then call harvest_bytes_written() which
8769 will harvest all these BIN_LOG_HEADER_SIZE we forgot), it may give strange
8770 output in SHOW REPLICA STATUS meanwhile. So we harvest now.
8771 If the log is closed, then this will just harvest the last writes, probably
8772 0 as they probably have been harvested.
8773 */
8774
1/2
✓ Branch 0 taken 23620 times.
✗ Branch 1 not taken.
23620 rli->relay_log.harvest_bytes_written(rli, need_log_space_lock);
8775 23624 end:
8776
3/4
✓ Branch 0 taken 5211 times.
✓ Branch 1 taken 18413 times.
✓ Branch 2 taken 5211 times.
✗ Branch 3 not taken.
23624 if (need_lock) mysql_mutex_unlock(rli->relay_log.get_log_lock());
8777 23624 return error;
8778 23624 }
8779
8780 /**
8781 flushes the relay logs of a replication channel.
8782
8783 @param[in] mi Master_info corresponding to the
8784 channel.
8785 @param[in] thd the client thread carrying the command.
8786
8787 @retval 1 fail
8788 @retval 0 ok
8789 @retval -1 deferred flush
8790 */
8791 6839 int flush_relay_logs(Master_info *mi, THD *thd) {
8792
1/2
✓ Branch 0 taken 6839 times.
✗ Branch 1 not taken.
6839 DBUG_TRACE;
8793 6839 int error = 0;
8794
8795
1/2
✓ Branch 0 taken 6839 times.
✗ Branch 1 not taken.
6839 if (mi) {
8796 6839 Relay_log_info *rli = mi->rli;
8797
2/2
✓ Branch 0 taken 5193 times.
✓ Branch 1 taken 1646 times.
6839 if (rli->inited) {
8798 // Rotate immediately if one is true:
8799
1/2
✓ Branch 0 taken 5193 times.
✗ Branch 1 not taken.
5193 if ((!is_group_replication_plugin_loaded() || // GR is disabled
8800
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4845 times.
4846 !mi->transaction_parser
8801 4846 .is_inside_transaction() || // not inside a transaction
8802
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 !channel_map.is_group_replication_channel_name(
8803 1 mi->get_channel(),
8804
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 true) || // channel isn't GR applier channel
8805
4/4
✓ Branch 0 taken 4846 times.
✓ Branch 1 taken 347 times.
✓ Branch 2 taken 5192 times.
✓ Branch 3 taken 1 times.
10387 !mi->slave_running) && // the I/O thread isn't running
8806
6/8
✓ Branch 0 taken 5193 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 5190 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 1 times.
5193 DBUG_EVALUATE_IF("deferred_flush_relay_log",
8807 !channel_map.is_group_replication_channel_name(
8808 mi->get_channel(), true),
8809 true)) {
8810
2/4
✓ Branch 0 taken 5186 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5186 times.
5192 if (rotate_relay_log(mi)) error = 1;
8811 }
8812 // Postpone the rotate action, delegating it to the I/O thread
8813 else {
8814
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 channel_map.unlock();
8815
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 mi->request_rotate(thd);
8816
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 channel_map.rdlock();
8817 1 error = -1;
8818 }
8819 }
8820 }
8821 6833 return error;
8822 6833 }
8823
8824 /**
8825 Entry point for FLUSH RELAYLOGS command or to flush relaylogs for
8826 the FLUSH LOGS command.
8827 FLUSH LOGS or FLUSH RELAYLOGS needs to flush the relaylogs of all
8828 the replciaiton channels in multisource replication.
8829 FLUSH RELAYLOGS FOR CHANNEL flushes only the relaylogs pertaining to
8830 a channel.
8831
8832 @param[in] thd the client thread carrying the command.
8833
8834 @retval true fail
8835 @retval false success
8836 */
8837 1868 bool flush_relay_logs_cmd(THD *thd) {
8838
1/2
✓ Branch 0 taken 1868 times.
✗ Branch 1 not taken.
1868 DBUG_TRACE;
8839 1868 Master_info *mi = nullptr;
8840 1868 LEX *lex = thd->lex;
8841 1868 bool error = false;
8842
8843
1/2
✓ Branch 0 taken 1868 times.
✗ Branch 1 not taken.
1868 channel_map.rdlock();
8844
8845 /*
8846 lex->mi.channel is NULL, for FLUSH LOGS or when the client thread
8847 is not present. (See tmp_thd in the caller).
8848 When channel is not provided, lex->mi.for_channel is false.
8849 */
8850
4/4
✓ Branch 0 taken 121 times.
✓ Branch 1 taken 1747 times.
✓ Branch 2 taken 95 times.
✓ Branch 3 taken 26 times.
1868 if (!lex->mi.channel || !lex->mi.for_channel) {
8851 1842 bool flush_was_deferred{false};
8852 1842 enum_channel_type channel_types[] = {SLAVE_REPLICATION_CHANNEL,
8853 GROUP_REPLICATION_CHANNEL};
8854
8855
2/2
✓ Branch 0 taken 3678 times.
✓ Branch 1 taken 1836 times.
5514 for (auto channel_type : channel_types) {
8856 3678 mi_map already_processed;
8857
8858
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3672 times.
3673 do {
8859 3679 flush_was_deferred = false;
8860
8861
1/2
✓ Branch 0 taken 3679 times.
✗ Branch 1 not taken.
3679 for (mi_map::iterator it = channel_map.begin(channel_type);
8862
3/4
✓ Branch 0 taken 5664 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1992 times.
✓ Branch 3 taken 3672 times.
5664 it != channel_map.end(channel_type); it++) {
8863
3/4
✓ Branch 0 taken 1992 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1991 times.
1992 if (already_processed.find(it->first) != already_processed.end())
8864 1 continue;
8865
8866 1991 mi = it->second;
8867
2/4
✓ Branch 0 taken 1991 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1991 times.
✗ Branch 3 not taken.
1991 already_processed.insert(std::make_pair(it->first, mi));
8868
8869
1/2
✓ Branch 0 taken 1985 times.
✗ Branch 1 not taken.
1991 int flush_status = flush_relay_logs(mi, thd);
8870 1985 flush_was_deferred = (flush_status == -1);
8871 1985 error = (flush_status == 1);
8872
8873
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1984 times.
1985 if (flush_status != 0) break;
8874 }
8875 } while (flush_was_deferred);
8876 3672 }
8877 #ifdef WITH_WSREP
8878 // GR use to have check like this. Now removed. PXC continue to enforce it.
8879
6/8
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 26 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 25 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 25 times.
1862 } else if (lex->mi.channel && wsrep_is_wsrep_channel_name(lex->mi.channel)) {
8880
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL ||
8881
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 thd->system_thread == SYSTEM_THREAD_SLAVE_WORKER) {
8882 /*
8883 Log warning on SQL or worker threads.
8884 */
8885 WSREP_ERROR("FLUSH RELAY LOGS cannot be performed on channel 'wsrep'");
8886 LogErr(WARNING_LEVEL, ER_RPL_SLAVE_INCORRECT_CHANNEL, lex->mi.channel);
8887 } else {
8888 /*
8889 Return error on client sessions.
8890 */
8891 1 error = true;
8892
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_SLAVE_CHANNEL_OPERATION_NOT_ALLOWED, MYF(0),
8893 "FLUSH RELAY LOGS", lex->mi.channel);
8894 }
8895 #endif /* WITH_WSREP */
8896 } else {
8897
1/2
✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
25 mi = channel_map.get_mi(lex->mi.channel);
8898
8899
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 6 times.
25 if (mi) {
8900
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 error = (flush_relay_logs(mi, thd) == 1);
8901 } else {
8902
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL ||
8903
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
6 thd->system_thread == SYSTEM_THREAD_SLAVE_WORKER) {
8904 /*
8905 Log warning on SQL or worker threads.
8906 */
8907
8/16
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 2 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 2 times.
✗ Branch 15 not taken.
2 LogErr(WARNING_LEVEL, ER_RPL_SLAVE_INCORRECT_CHANNEL, lex->mi.channel);
8908 } else {
8909 /*
8910 Return error on client sessions.
8911 */
8912 4 error = true;
8913
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 my_error(ER_SLAVE_CHANNEL_DOES_NOT_EXIST, MYF(0), lex->mi.channel);
8914 }
8915 }
8916 }
8917
8918
1/2
✓ Branch 0 taken 1862 times.
✗ Branch 1 not taken.
1862 channel_map.unlock();
8919
8920 1862 return error;
8921 1862 }
8922
8923 66 bool reencrypt_relay_logs() {
8924
1/2
✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
66 DBUG_TRACE;
8925
8926 Master_info *mi;
8927
1/2
✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
66 channel_map.rdlock();
8928
8929 66 enum_channel_type channel_types[] = {SLAVE_REPLICATION_CHANNEL,
8930 GROUP_REPLICATION_CHANNEL};
8931
2/2
✓ Branch 0 taken 129 times.
✓ Branch 1 taken 63 times.
192 for (auto channel_type : channel_types) {
8932
1/2
✓ Branch 0 taken 129 times.
✗ Branch 1 not taken.
129 for (mi_map::iterator it = channel_map.begin(channel_type);
8933
3/4
✓ Branch 0 taken 192 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 66 times.
✓ Branch 3 taken 126 times.
192 it != channel_map.end(channel_type); it++) {
8934 66 mi = it->second;
8935
1/2
✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
66 if (mi != nullptr) {
8936 66 Relay_log_info *rli = mi->rli;
8937
8/10
✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 58 times.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✓ Branch 7 taken 5 times.
✓ Branch 8 taken 3 times.
✓ Branch 9 taken 63 times.
66 if (rli != nullptr && rli->inited && rli->relay_log.reencrypt_logs()) {
8938
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 channel_map.unlock();
8939 3 return true;
8940 }
8941 }
8942 }
8943 }
8944
8945
1/2
✓ Branch 0 taken 63 times.
✗ Branch 1 not taken.
63 channel_map.unlock();
8946
8947 63 return false;
8948 66 }
8949
8950 /**
8951 Detects, based on master's version (as found in the relay log), if master
8952 has a certain bug.
8953 @param rli Relay_log_info which tells the master's version
8954 @param bug_id Number of the bug as found in bugs.mysql.com
8955 @param report bool report error message, default true
8956
8957 @param pred Predicate function that will be called with @c param to
8958 check for the bug. If the function return @c true, the bug is present,
8959 otherwise, it is not.
8960
8961 @param param State passed to @c pred function.
8962
8963 @return true if master has the bug, false if it does not.
8964 */
8965 142151 bool rpl_master_has_bug(const Relay_log_info *rli, uint bug_id, bool report,
8966 bool (*pred)(const void *), const void *param) {
8967 struct st_version_range_for_one_bug {
8968 uint bug_id;
8969 const uchar introduced_in[3]; // first version with bug
8970 const uchar fixed_in[3]; // first version with fix
8971 };
8972 static struct st_version_range_for_one_bug versions_for_all_bugs[] = {
8973 {24432, {5, 0, 24}, {5, 0, 38}}, {24432, {5, 1, 12}, {5, 1, 17}},
8974 {33029, {5, 0, 0}, {5, 0, 58}}, {33029, {5, 1, 0}, {5, 1, 12}},
8975 {37426, {5, 1, 0}, {5, 1, 26}},
8976 };
8977 const uchar *master_ver =
8978 142151 rli->get_rli_description_event()->server_version_split;
8979
8980 assert(sizeof(rli->get_rli_description_event()->server_version_split) == 3);
8981
8982 852889 for (uint i = 0;
8983
2/2
✓ Branch 0 taken 710743 times.
✓ Branch 1 taken 142146 times.
852889 i < sizeof(versions_for_all_bugs) / sizeof(*versions_for_all_bugs);
8984 i++) {
8985 710743 const uchar *introduced_in = versions_for_all_bugs[i].introduced_in,
8986 710743 *fixed_in = versions_for_all_bugs[i].fixed_in;
8987 1705336 if ((versions_for_all_bugs[i].bug_id == bug_id) &&
8988
2/2
✓ Branch 0 taken 283736 times.
✓ Branch 1 taken 114 times.
283850 (memcmp(introduced_in, master_ver, 3) <= 0) &&
8989
8/8
✓ Branch 0 taken 283850 times.
✓ Branch 1 taken 426893 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 283727 times.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 4 times.
✓ Branch 6 taken 5 times.
✓ Branch 7 taken 710738 times.
994598 (memcmp(fixed_in, master_ver, 3) > 0) &&
8990
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
5 (pred == nullptr || (*pred)(param))) {
8991
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3 times.
5 if (!report) return true;
8992 // a short message for SHOW REPLICA STATUS (message length constraints)
8993 3 my_printf_error(ER_UNKNOWN_ERROR,
8994 "master may suffer from"
8995 " http://bugs.mysql.com/bug.php?id=%u"
8996 " so slave stops; check error log on slave"
8997 " for more info",
8998 MYF(0), bug_id);
8999 // a verbose message for the error log
9000 3 enum loglevel report_level = INFORMATION_LEVEL;
9001
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (!ignored_error_code(ER_UNKNOWN_ERROR)) {
9002 3 report_level = ERROR_LEVEL;
9003 3 current_thd->is_slave_error = true;
9004 } else if (log_error_verbosity >= 2)
9005 report_level = WARNING_LEVEL;
9006
9007
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (report_level != INFORMATION_LEVEL)
9008 6 rli->report(report_level, ER_SERVER_UNKNOWN_ERROR,
9009 "According to the master's version ('%s'),"
9010 " it is probable that master suffers from this bug:"
9011 " http://bugs.mysql.com/bug.php?id=%u"
9012 " and thus replicating the current binary log event"
9013 " may make the slave's data become different from the"
9014 " master's data."
9015 " To take no risk, slave refuses to replicate"
9016 " this event and stops."
9017 " We recommend that all updates be stopped on the"
9018 " master and slave, that the data of both be"
9019 " manually synchronized,"
9020 " that master's binary logs be deleted,"
9021 " that master be upgraded to a version at least"
9022 " equal to '%d.%d.%d'. Then replication can be"
9023 " restarted.",
9024 3 rli->get_rli_description_event()->server_version, bug_id,
9025 3 fixed_in[0], fixed_in[1], fixed_in[2]);
9026 3 return true;
9027 }
9028 }
9029 142146 return false;
9030 }
9031
9032 /**
9033 BUG#33029, For all 5.0 up to 5.0.58 exclusive, and 5.1 up to 5.1.12
9034 exclusive, if one statement in a SP generated AUTO_INCREMENT value
9035 by the top statement, all statements after it would be considered
9036 generated AUTO_INCREMENT value by the top statement, and a
9037 erroneous INSERT_ID value might be associated with these statement,
9038 which could cause duplicate entry error and stop the slave.
9039
9040 Detect buggy master to work around.
9041 */
9042 931100 bool rpl_master_erroneous_autoinc(THD *thd) {
9043
3/4
✓ Branch 0 taken 141676 times.
✓ Branch 1 taken 789424 times.
✓ Branch 2 taken 141676 times.
✗ Branch 3 not taken.
931100 if (thd->rli_slave && thd->rli_slave->info_thd == thd) {
9044 141676 Relay_log_info *c_rli = thd->rli_slave->get_c_rli();
9045
9046
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 141676 times.
141676 DBUG_EXECUTE_IF("simulate_bug33029", return true;);
9047 141676 return rpl_master_has_bug(c_rli, 33029, false, nullptr, nullptr);
9048 }
9049 789424 return false;
9050 }
9051
9052 /**
9053 a copy of active_mi->rli->slave_skip_counter, for showing in SHOW GLOBAL
9054 VARIABLES, INFORMATION_SCHEMA.GLOBAL_VARIABLES and @@sql_replica_skip_counter
9055 without taking all the mutexes needed to access
9056 active_mi->rli->slave_skip_counter properly.
9057 */
9058 uint sql_replica_skip_counter;
9059
9060 /**
9061 Executes a START SLAVE statement.
9062
9063 @param thd Pointer to THD object for the client thread
9064 executing the statement.
9065
9066 @param connection_param Connection parameters for starting threads
9067
9068 @param master_param Master parameters used for starting threads
9069
9070 @param thread_mask_input The thread mask that identifies which threads to
9071 start. If 0 is passed (start no thread) then this
9072 parameter is ignored and all stopped threads are
9073 started
9074
9075 @param mi Pointer to Master_info object for the slave's IO
9076 thread.
9077
9078 @param set_mts_settings If true, the channel uses the server MTS
9079 configured settings when starting the applier
9080 thread.
9081
9082 @retval false success
9083 @retval true error
9084 */
9085 10713 bool start_slave(THD *thd, LEX_SLAVE_CONNECTION *connection_param,
9086 LEX_MASTER_INFO *master_param, int thread_mask_input,
9087 Master_info *mi, bool set_mts_settings) {
9088 10713 bool is_error = false;
9089 int thread_mask;
9090
9091
1/2
✓ Branch 0 taken 10713 times.
✗ Branch 1 not taken.
10713 DBUG_TRACE;
9092
9093 /*
9094 START SLAVE command should ignore 'read-only' and 'super_read_only'
9095 options so that it can update 'mysql.slave_master_info' and
9096 'mysql.slave_relay_log_info' replication repository tables.
9097 */
9098 10713 thd->set_skip_readonly_check();
9099 10713 Security_context *sctx = thd->security_context();
9100
8/16
✓ Branch 0 taken 10713 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10713 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 10710 times.
✓ Branch 6 taken 10713 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 10713 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✓ Branch 11 taken 10712 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
10716 if (!sctx->check_access(SUPER_ACL) &&
9101
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 !sctx->has_global_grant(STRING_WITH_LEN("REPLICATION_SLAVE_ADMIN"))
9102
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 .first) {
9103
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0),
9104 "SUPER or REPLICATION_SLAVE_ADMIN");
9105 1 return true;
9106 }
9107
9108
1/2
✓ Branch 0 taken 10712 times.
✗ Branch 1 not taken.
10712 mi->channel_wrlock();
9109
9110
4/4
✓ Branch 0 taken 10563 times.
✓ Branch 1 taken 149 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 10560 times.
10712 if (connection_param->user || connection_param->password) {
9111
3/4
✓ Branch 0 taken 152 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 116 times.
✓ Branch 3 taken 36 times.
152 if (!thd->get_ssl()) {
9112
2/4
✓ Branch 0 taken 116 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 116 times.
✗ Branch 3 not taken.
116 push_warning(thd, Sql_condition::SL_NOTE, ER_INSECURE_PLAIN_TEXT,
9113 ER_THD(thd, ER_INSECURE_PLAIN_TEXT));
9114 }
9115 }
9116
9117
1/2
✓ Branch 0 taken 10712 times.
✗ Branch 1 not taken.
10712 lock_slave_threads(mi); // this allows us to cleanly read slave_running
9118 // Get a mask of _stopped_ threads
9119
1/2
✓ Branch 0 taken 10712 times.
✗ Branch 1 not taken.
10712 init_thread_mask(&thread_mask, mi, true /* inverse */);
9120 /*
9121 Below we will start all stopped threads. But if the user wants to
9122 start only one thread, do as if the other thread was running (as we
9123 don't want to touch the other thread), so set the bit to 0 for the
9124 other thread
9125 */
9126
2/2
✓ Branch 0 taken 5427 times.
✓ Branch 1 taken 5285 times.
10712 if (thread_mask_input) {
9127 5427 thread_mask &= thread_mask_input;
9128 }
9129
2/2
✓ Branch 0 taken 10678 times.
✓ Branch 1 taken 34 times.
10712 if (thread_mask) // some threads are stopped, start them
9130 {
9131
3/4
✓ Branch 0 taken 10672 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 10667 times.
10678 if (load_mi_and_rli_from_repositories(mi, false, thread_mask)) {
9132 5 is_error = true;
9133
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 my_error(ER_MASTER_INFO, MYF(0));
9134
4/4
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 10656 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 9 times.
10667 } else if (*mi->host || !(thread_mask & SLAVE_IO)) {
9135 /*
9136 If we will start IO thread we need to take care of possible
9137 options provided through the START SLAVE if there is any.
9138 */
9139
2/2
✓ Branch 0 taken 6967 times.
✓ Branch 1 taken 3691 times.
10658 if (thread_mask & SLAVE_IO) {
9140
2/2
✓ Branch 0 taken 149 times.
✓ Branch 1 taken 6818 times.
6967 if (connection_param->user) {
9141 149 mi->set_start_user_configured(true);
9142
1/2
✓ Branch 0 taken 149 times.
✗ Branch 1 not taken.
149 mi->set_user(connection_param->user);
9143 }
9144
2/2
✓ Branch 0 taken 118 times.
✓ Branch 1 taken 6849 times.
6967 if (connection_param->password) {
9145 118 mi->set_start_user_configured(true);
9146
1/2
✓ Branch 0 taken 118 times.
✗ Branch 1 not taken.
118 mi->set_password(connection_param->password);
9147 }
9148
2/2
✓ Branch 0 taken 62 times.
✓ Branch 1 taken 6905 times.
6967 if (connection_param->plugin_auth)
9149
1/2
✓ Branch 0 taken 62 times.
✗ Branch 1 not taken.
62 mi->set_plugin_auth(connection_param->plugin_auth);
9150
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 6925 times.
6967 if (connection_param->plugin_dir)
9151
1/2
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
42 mi->set_plugin_dir(connection_param->plugin_dir);
9152 }
9153
9154 /*
9155 If we will start SQL thread we will care about UNTIL options If
9156 not and they are specified we will ignore them and warn user
9157 about this fact.
9158 */
9159
2/2
✓ Branch 0 taken 9933 times.
✓ Branch 1 taken 725 times.
10658 if (thread_mask & SLAVE_SQL) {
9160 /*
9161 sql_replica_skip_counter only effects the applier thread which is
9162 first started. So after sql_replica_skip_counter is copied to
9163 rli->slave_skip_counter, it is reset to 0.
9164 */
9165
1/2
✓ Branch 0 taken 9933 times.
✗ Branch 1 not taken.
9933 mysql_mutex_lock(&LOCK_sql_replica_skip_counter);
9166
1/2
✓ Branch 0 taken 9933 times.
✗ Branch 1 not taken.
9933 if (mi->rli->m_assign_gtids_to_anonymous_transactions_info.get_type() !=
9167 Assign_gtids_to_anonymous_transactions_info::enum_type::
9168
4/4
✓ Branch 0 taken 9905 times.
✓ Branch 1 taken 28 times.
✓ Branch 2 taken 5119 times.
✓ Branch 3 taken 4814 times.
19838 AGAT_OFF ||
9169
3/4
✓ Branch 0 taken 9905 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5091 times.
✓ Branch 3 taken 4814 times.
9905 global_gtid_mode.get() != Gtid_mode::ON)
9170 5119 mi->rli->slave_skip_counter = sql_replica_skip_counter;
9171 9933 sql_replica_skip_counter = 0;
9172
1/2
✓ Branch 0 taken 9933 times.
✗ Branch 1 not taken.
9933 mysql_mutex_unlock(&LOCK_sql_replica_skip_counter);
9173 /*
9174 To cache the MTS system var values and used them in the following
9175 runtime. The system vars can change meanwhile but having no other
9176 effects.
9177 It also allows the per channel definition of this variables.
9178 */
9179
2/2
✓ Branch 0 taken 9931 times.
✓ Branch 1 taken 2 times.
9933 if (set_mts_settings) {
9180 9931 mi->rli->opt_replica_parallel_workers =
9181 opt_mts_replica_parallel_workers;
9182
5/6
✓ Branch 0 taken 9931 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3681 times.
✓ Branch 3 taken 6250 times.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 9926 times.
13612 if (mi->is_gtid_only_mode() &&
9183
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 3676 times.
3681 opt_mts_replica_parallel_workers == 0) {
9184 5 mi->rli->opt_replica_parallel_workers = 1;
9185 }
9186
2/2
✓ Branch 0 taken 51 times.
✓ Branch 1 taken 9880 times.
9931 if (mts_parallel_option == MTS_PARALLEL_TYPE_DB_NAME)
9187 51 mi->rli->channel_mts_submode = MTS_PARALLEL_TYPE_DB_NAME;
9188 else
9189 9880 mi->rli->channel_mts_submode = MTS_PARALLEL_TYPE_LOGICAL_CLOCK;
9190
9191 #ifndef NDEBUG
9192
2/4
✓ Branch 0 taken 9931 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9931 times.
✗ Branch 3 not taken.
9931 if (!DBUG_EVALUATE_IF("check_replica_debug_group", 1, 0))
9193 #endif
9194 9931 mi->rli->checkpoint_group = opt_mta_checkpoint_group;
9195 }
9196
9197
1/2
✓ Branch 0 taken 9933 times.
✗ Branch 1 not taken.
9933 int slave_errno = mi->rli->init_until_option(thd, master_param);
9198
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 9927 times.
9933 if (slave_errno) {
9199
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 my_error(slave_errno, MYF(0));
9200 6 is_error = true;
9201 }
9202
9203
3/4
✓ Branch 0 taken 9927 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 9927 times.
✗ Branch 3 not taken.
9933 if (!is_error) is_error = check_slave_sql_config_conflict(mi->rli);
9204
2/4
✓ Branch 0 taken 725 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 725 times.
✗ Branch 3 not taken.
725 } else if (master_param->pos || master_param->relay_log_pos ||
9205
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 723 times.
725 master_param->gtid)
9206
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 push_warning(thd, Sql_condition::SL_NOTE, ER_UNTIL_COND_IGNORED,
9207 ER_THD(thd, ER_UNTIL_COND_IGNORED));
9208
9209
2/2
✓ Branch 0 taken 10646 times.
✓ Branch 1 taken 12 times.
10658 if (!is_error)
9210 is_error =
9211
1/2
✓ Branch 0 taken 10646 times.
✗ Branch 1 not taken.
10646 start_slave_threads(false /*need_lock_slave=false*/,
9212 true /*wait_for_start=true*/, mi, thread_mask);
9213 10658 } else {
9214 9 is_error = true;
9215
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 my_error(ER_BAD_SLAVE, MYF(0));
9216 }
9217 } else {
9218 /* no error if all threads are already started, only a warning */
9219
2/4
✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 34 times.
✗ Branch 3 not taken.
34 push_warning_printf(
9220 thd, Sql_condition::SL_NOTE, ER_SLAVE_CHANNEL_WAS_RUNNING,
9221 ER_THD(thd, ER_SLAVE_CHANNEL_WAS_RUNNING), mi->get_channel());
9222 }
9223
9224 /*
9225 Clean up start information if there was an attempt to start
9226 the IO thread to avoid any security issue.
9227 */
9228
5/6
✓ Branch 0 taken 49 times.
✓ Branch 1 taken 10657 times.
✓ Branch 2 taken 34 times.
✓ Branch 3 taken 15 times.
✓ Branch 4 taken 34 times.
✗ Branch 5 not taken.
10706 if (is_error && (thread_mask & SLAVE_IO) == SLAVE_IO) mi->reset_start_info();
9229
9230
1/2
✓ Branch 0 taken 10706 times.
✗ Branch 1 not taken.
10706 unlock_slave_threads(mi);
9231
9232
1/2
✓ Branch 0 taken 10706 times.
✗ Branch 1 not taken.
10706 mi->channel_unlock();
9233
9234 10706 return is_error;
9235 10707 }
9236
9237 /**
9238 Execute a STOP SLAVE statement.
9239
9240 @param thd Pointer to THD object for the client thread executing
9241 the statement.
9242
9243 @param mi Pointer to Master_info object for the slave's IO
9244 thread.
9245
9246 @param net_report If true, saves the exit status into Diagnostics_area.
9247
9248 @param for_one_channel If the method is being invoked only for one channel
9249
9250 @param push_temp_tables_warning If it should push a "have temp tables
9251 warning" once having open temp tables. This
9252 avoids multiple warnings when there is more
9253 than one channel with open temp tables.
9254 This parameter can be removed when the
9255 warning is issued with per-channel
9256 information.
9257
9258 @retval 0 success
9259 @retval 1 error
9260 */
9261 5962 int stop_slave(THD *thd, Master_info *mi, bool net_report, bool for_one_channel,
9262 bool *push_temp_tables_warning) {
9263
1/2
✓ Branch 0 taken 5962 times.
✗ Branch 1 not taken.
5962 DBUG_TRACE;
9264
9265 int slave_errno;
9266
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 5962 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
5962 if (!thd) thd = current_thd;
9267
9268 /*
9269 STOP SLAVE command should ignore 'read-only' and 'super_read_only'
9270 options so that it can update 'mysql.slave_master_info' and
9271 'mysql.slave_relay_log_info' replication repository tables.
9272 */
9273 5962 thd->set_skip_readonly_check();
9274
9275 5962 Security_context *sctx = thd->security_context();
9276
8/16
✓ Branch 0 taken 5962 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5962 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 5961 times.
✓ Branch 6 taken 5962 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5962 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✓ Branch 11 taken 5961 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
5963 if (!sctx->check_access(SUPER_ACL) &&
9277
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 !sctx->has_global_grant(STRING_WITH_LEN("REPLICATION_SLAVE_ADMIN"))
9278
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 .first) {
9279
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0),
9280 "SUPER or REPLICATION_SLAVE_ADMIN");
9281 1 return 1;
9282 }
9283
9284
1/2
✓ Branch 0 taken 5961 times.
✗ Branch 1 not taken.
5961 mi->channel_wrlock();
9285
9286
1/2
✓ Branch 0 taken 5961 times.
✗ Branch 1 not taken.
5961 THD_STAGE_INFO(thd, stage_killing_replica);
9287 int thread_mask;
9288
1/2
✓ Branch 0 taken 5961 times.
✗ Branch 1 not taken.
5961 lock_slave_threads(mi);
9289
9290
2/6
✓ Branch 0 taken 5961 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5961 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
5961 DBUG_EXECUTE_IF("simulate_hold_run_locks_on_stop_replica",
9291 my_sleep(10000000););
9292
9293 // Get a mask of _running_ threads
9294
1/2
✓ Branch 0 taken 5961 times.
✗ Branch 1 not taken.
5961 init_thread_mask(&thread_mask, mi, false /* not inverse*/);
9295
9296 /*
9297 Below we will stop all running threads.
9298 But if the user wants to stop only one thread, do as if the other thread
9299 was stopped (as we don't want to touch the other thread), so set the
9300 bit to 0 for the other thread
9301 */
9302
2/2
✓ Branch 0 taken 1281 times.
✓ Branch 1 taken 4680 times.
5961 if (thd->lex->slave_thd_opt) {
9303 1281 thread_mask &= thd->lex->slave_thd_opt;
9304
9305 /*
9306 If we are stopping IO thread, we also need to consider
9307 IO Monitor thread.
9308 */
9309
6/6
✓ Branch 0 taken 562 times.
✓ Branch 1 taken 719 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 556 times.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 1275 times.
1281 if ((thread_mask & SLAVE_IO) && mi->is_source_connection_auto_failover()) {
9310 6 thread_mask |= SLAVE_MONITOR;
9311 }
9312 }
9313
9314
2/2
✓ Branch 0 taken 5716 times.
✓ Branch 1 taken 245 times.
5961 if (thread_mask) {
9315 slave_errno =
9316
1/2
✓ Branch 0 taken 5716 times.
✗ Branch 1 not taken.
5716 terminate_slave_threads(mi, thread_mask, rpl_stop_replica_timeout,
9317 false /*need_lock_term=false*/);
9318 } else {
9319 // no error if both threads are already stopped, only a warning
9320 245 slave_errno = 0;
9321
2/4
✓ Branch 0 taken 245 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 245 times.
✗ Branch 3 not taken.
245 push_warning_printf(
9322 thd, Sql_condition::SL_NOTE, ER_SLAVE_CHANNEL_WAS_NOT_RUNNING,
9323 ER_THD(thd, ER_SLAVE_CHANNEL_WAS_NOT_RUNNING), mi->get_channel());
9324 }
9325
9326 /*
9327 If the slave has open temp tables and there is a following CHANGE MASTER
9328 there is a possibility that the temporary tables are left open forever.
9329 Though we dont restrict failover here, we do warn users. In future, we
9330 should have a command to delete open temp tables the slave has replicated.
9331 See WL#7441 regarding this command.
9332 */
9333
9334
6/6
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 5941 times.
✓ Branch 2 taken 19 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 19 times.
✓ Branch 5 taken 5942 times.
5961 if (mi->rli->atomic_channel_open_temp_tables && *push_temp_tables_warning) {
9335
2/4
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19 times.
✗ Branch 3 not taken.
19 push_warning(thd, Sql_condition::SL_WARNING,
9336 ER_WARN_OPEN_TEMP_TABLES_MUST_BE_ZERO,
9337 ER_THD(thd, ER_WARN_OPEN_TEMP_TABLES_MUST_BE_ZERO));
9338 19 *push_temp_tables_warning = false;
9339 }
9340
9341
1/2
✓ Branch 0 taken 5961 times.
✗ Branch 1 not taken.
5961 unlock_slave_threads(mi);
9342
9343
1/2
✓ Branch 0 taken 5961 times.
✗ Branch 1 not taken.
5961 mi->channel_unlock();
9344
9345
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5961 times.
5961 if (slave_errno) {
9346 if ((slave_errno == ER_STOP_SLAVE_SQL_THREAD_TIMEOUT) ||
9347 (slave_errno == ER_STOP_REPLICA_MONITOR_IO_THREAD_TIMEOUT) ||
9348 (slave_errno == ER_STOP_SLAVE_IO_THREAD_TIMEOUT)) {
9349 push_warning(thd, Sql_condition::SL_NOTE, slave_errno,
9350 ER_THD_NONCONST(thd, slave_errno));
9351
9352 /*
9353 If new slave_errno is added in the if() condition above then make sure
9354 that there are no % in the error message or change the logging API
9355 to use verbatim() to avoid % substitutions.
9356 */
9357 longlong log_errno = (slave_errno == ER_STOP_SLAVE_SQL_THREAD_TIMEOUT)
9358 ? ER_RPL_SLAVE_SQL_THREAD_STOP_CMD_EXEC_TIMEOUT
9359 : ER_RPL_SLAVE_IO_THREAD_STOP_CMD_EXEC_TIMEOUT;
9360 LogErr(WARNING_LEVEL, log_errno);
9361 }
9362 if (net_report) my_error(slave_errno, MYF(0));
9363 return 1;
9364
3/4
✓ Branch 0 taken 5961 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 426 times.
✓ Branch 3 taken 5535 times.
5961 } else if (net_report && for_one_channel)
9365
1/2
✓ Branch 0 taken 426 times.
✗ Branch 1 not taken.
426 my_ok(thd);
9366
9367 5961 return 0;
9368 5962 }
9369
9370 /**
9371 Execute a RESET SLAVE (for all channels), used in Multisource replication.
9372 If resetting of a particular channel fails, it exits out.
9373
9374 @param[in] thd THD object of the client.
9375
9376 @retval 0 success
9377 @retval 1 error
9378 */
9379
9380 1321 int reset_slave(THD *thd) {
9381
1/2
✓ Branch 0 taken 1321 times.
✗ Branch 1 not taken.
1321 DBUG_TRACE;
9382
9383
1/2
✓ Branch 0 taken 1321 times.
✗ Branch 1 not taken.
1321 channel_map.assert_some_wrlock();
9384
9385 1321 Master_info *mi = nullptr;
9386 1321 int result = 0;
9387 1321 mi_map::iterator it, gr_channel_map_it;
9388
2/2
✓ Branch 0 taken 347 times.
✓ Branch 1 taken 974 times.
1321 if (thd->lex->reset_slave_info.all) {
9389 /* First do reset_slave for default channel */
9390
1/2
✓ Branch 0 taken 347 times.
✗ Branch 1 not taken.
347 mi = channel_map.get_default_channel_mi();
9391
6/8
✓ Branch 0 taken 347 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 347 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 346 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 346 times.
347 if (mi && reset_slave(thd, mi, thd->lex->reset_slave_info.all)) return 1;
9392 /* Do while iteration for rest of the channels */
9393
1/2
✓ Branch 0 taken 346 times.
✗ Branch 1 not taken.
346 it = channel_map.begin();
9394
3/4
✓ Branch 0 taken 766 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 420 times.
✓ Branch 3 taken 346 times.
766 while (it != channel_map.end()) {
9395
2/2
✓ Branch 0 taken 383 times.
✓ Branch 1 taken 37 times.
420 if (!it->first.compare(channel_map.get_default_channel())) {
9396 383 it++;
9397 383 continue;
9398 }
9399 37 mi = it->second;
9400
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
37 assert(mi);
9401
2/4
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 37 times.
37 if ((result = reset_slave(thd, mi, thd->lex->reset_slave_info.all)))
9402 break;
9403
1/2
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
37 it = channel_map.begin();
9404 }
9405 /* RESET group replication specific channels */
9406
1/2
✓ Branch 0 taken 346 times.
✗ Branch 1 not taken.
346 gr_channel_map_it = channel_map.begin(GROUP_REPLICATION_CHANNEL);
9407
3/4
✓ Branch 0 taken 351 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 345 times.
351 while (gr_channel_map_it != channel_map.end(GROUP_REPLICATION_CHANNEL)) {
9408 6 mi = gr_channel_map_it->second;
9409
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 assert(mi);
9410 /*
9411 We cannot RESET a group replication channel while the group
9412 replication is running.
9413 */
9414
3/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 5 times.
6 if (is_group_replication_running()) {
9415
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_SLAVE_CHANNEL_OPERATION_NOT_ALLOWED, MYF(0),
9416 "RESET SLAVE ALL FOR CHANNEL", mi->get_channel());
9417 1 return 1;
9418 }
9419
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 if ((result = reset_slave(thd, mi, thd->lex->reset_slave_info.all)))
9420 break;
9421
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 gr_channel_map_it = channel_map.begin(GROUP_REPLICATION_CHANNEL);
9422 }
9423 } else {
9424
1/2
✓ Branch 0 taken 974 times.
✗ Branch 1 not taken.
974 it = channel_map.begin();
9425
3/4
✓ Branch 0 taken 1948 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 977 times.
✓ Branch 3 taken 971 times.
1948 while (it != channel_map.end()) {
9426 977 mi = it->second;
9427
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 977 times.
977 assert(mi);
9428
3/4
✓ Branch 0 taken 977 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 974 times.
977 if ((result = reset_slave(thd, mi, thd->lex->reset_slave_info.all)))
9429 3 break;
9430 974 it++;
9431 }
9432 /*
9433 RESET group replication specific channels.
9434
9435 We cannot RESET a group replication channel while the group
9436 replication is running.
9437 */
9438
1/2
✓ Branch 0 taken 974 times.
✗ Branch 1 not taken.
974 gr_channel_map_it = channel_map.begin(GROUP_REPLICATION_CHANNEL);
9439
3/4
✓ Branch 0 taken 979 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 974 times.
979 while (gr_channel_map_it != channel_map.end(GROUP_REPLICATION_CHANNEL)) {
9440 5 mi = gr_channel_map_it->second;
9441
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 assert(mi);
9442
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 if (is_group_replication_running()) {
9443 my_error(ER_SLAVE_CHANNEL_OPERATION_NOT_ALLOWED, MYF(0),
9444 "RESET SLAVE FOR CHANNEL", mi->get_channel());
9445 return 1;
9446 }
9447
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 if ((result = reset_slave(thd, mi, thd->lex->reset_slave_info.all)))
9448 break;
9449 5 gr_channel_map_it++;
9450 }
9451 }
9452 1319 return result;
9453 1321 }
9454
9455 /**
9456 Execute a RESET REPLICA statement.
9457 Locks slave threads and unlocks the slave threads after executing
9458 reset slave.
9459 The method also takes the mi->channel_wrlock; if this {mi} object
9460 is deleted (when the parameter reset_all is true) its destructor unlocks
9461 the lock. In case of error, the method shall always unlock the
9462 mi channel lock.
9463
9464 @param thd Pointer to THD object of the client thread executing the
9465 statement.
9466
9467 @param mi Pointer to Master_info object for the slave.
9468
9469 @param reset_all Do a full reset or only clean master info structures
9470
9471 @retval 0 success
9472 @retval !=0 error
9473 */
9474 12602 int reset_slave(THD *thd, Master_info *mi, bool reset_all) {
9475 12602 int thread_mask = 0, error = 0;
9476 12602 const char *errmsg = "Unknown error occurred while reseting slave";
9477
1/2
✓ Branch 0 taken 12602 times.
✗ Branch 1 not taken.
12602 DBUG_TRACE;
9478
9479 bool is_default_channel =
9480 12602 strcmp(mi->get_channel(), channel_map.get_default_channel()) == 0;
9481
9482 /*
9483 RESET SLAVE command should ignore 'read-only' and 'super_read_only'
9484 options so that it can update 'mysql.slave_master_info' and
9485 'mysql.slave_relay_log_info' replication repository tables.
9486 */
9487 12602 thd->set_skip_readonly_check();
9488
1/2
✓ Branch 0 taken 12602 times.
✗ Branch 1 not taken.
12602 mi->channel_wrlock();
9489
9490
1/2
✓ Branch 0 taken 12602 times.
✗ Branch 1 not taken.
12602 lock_slave_threads(mi);
9491
1/2
✓ Branch 0 taken 12602 times.
✗ Branch 1 not taken.
12602 init_thread_mask(&thread_mask, mi, false /* not inverse */,
9492 true /* ignore_monitor_thread */);
9493
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 12600 times.
12602 if (thread_mask) // We refuse if any slave thread is running
9494 {
9495
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_error(ER_SLAVE_CHANNEL_MUST_STOP, MYF(0), mi->get_channel());
9496 2 error = ER_SLAVE_CHANNEL_MUST_STOP;
9497
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 unlock_slave_threads(mi);
9498
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 mi->channel_unlock();
9499 2 goto err;
9500 }
9501
9502
1/2
✓ Branch 0 taken 12600 times.
✗ Branch 1 not taken.
12600 ha_reset_slave(thd);
9503
9504 // delete relay logs, clear relay log coordinates
9505
3/4
✓ Branch 0 taken 12600 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 12597 times.
12600 if ((error = mi->rli->purge_relay_logs(thd, &errmsg,
9506
4/4
✓ Branch 0 taken 8923 times.
✓ Branch 1 taken 3677 times.
✓ Branch 2 taken 2866 times.
✓ Branch 3 taken 6057 times.
12600 reset_all && !is_default_channel))) {
9507
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 my_error(ER_RELAY_LOG_FAIL, MYF(0), errmsg);
9508 3 error = ER_RELAY_LOG_FAIL;
9509
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 unlock_slave_threads(mi);
9510
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 mi->channel_unlock();
9511 3 goto err;
9512 }
9513
9514
2/4
✓ Branch 0 taken 12597 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12597 times.
12597 assert(!mi->rli || !mi->rli->slave_running); // none writes in rli table
9515
7/8
✓ Branch 0 taken 8923 times.
✓ Branch 1 taken 3674 times.
✓ Branch 2 taken 8923 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8922 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 12596 times.
25193 if ((reset_all && remove_info(mi)) || // Removes all repository information.
9516
4/6
✓ Branch 0 taken 3674 times.
✓ Branch 1 taken 8922 times.
✓ Branch 2 taken 3674 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3674 times.
12596 (!reset_all && reset_info(mi))) { // Resets log names, positions, etc,
9517 // but keeps configuration information
9518 // needed for a re-connection.
9519 1 error = ER_UNKNOWN_ERROR;
9520
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_UNKNOWN_ERROR, MYF(0));
9521
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 unlock_slave_threads(mi);
9522
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 mi->channel_unlock();
9523 1 goto err;
9524 }
9525
1/2
✓ Branch 0 taken 12596 times.
✗ Branch 1 not taken.
12596 unlock_slave_threads(mi);
9526
9527
4/6
✓ Branch 0 taken 12596 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7027 times.
✓ Branch 3 taken 5569 times.
✓ Branch 4 taken 7027 times.
✗ Branch 5 not taken.
12596 (void)RUN_HOOK(binlog_relay_io, after_reset_slave, (thd, mi));
9528
9529 /*
9530 RESET SLAVE ALL deletes the channels(except default channel), so their mi
9531 and rli objects are removed. For default channel, its mi and rli are
9532 deleted and recreated to keep in clear status.
9533 */
9534
2/2
✓ Branch 0 taken 8922 times.
✓ Branch 1 taken 3674 times.
12596 if (reset_all) {
9535 bool is_default =
9536 8922 !strcmp(mi->get_channel(), channel_map.get_default_channel());
9537
9538
2/4
✓ Branch 0 taken 8922 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8922 times.
✗ Branch 3 not taken.
17844 rpl_acf_configuration_handler->delete_channel_status(
9539 8922 mi->get_channel(),
9540 Rpl_acf_status_configuration::SOURCE_CONNECTION_AUTO_FAILOVER);
9541
9542 // delete_mi will call mi->channel_unlock in case it succeeds
9543
2/4
✓ Branch 0 taken 8922 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 8922 times.
8922 if (channel_map.delete_mi(mi->get_channel())) {
9544 mi->channel_unlock();
9545 error = ER_UNKNOWN_ERROR;
9546 my_error(ER_UNKNOWN_ERROR, MYF(0));
9547 goto err;
9548 }
9549
9550
2/2
✓ Branch 0 taken 6057 times.
✓ Branch 1 taken 2865 times.
8922 if (is_default) {
9551
3/4
✓ Branch 0 taken 6057 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 6056 times.
6057 if (!Rpl_info_factory::create_mi_and_rli_objects(
9552 opt_mi_repository_id, opt_rli_repository_id,
9553 channel_map.get_default_channel(), true, &channel_map)) {
9554 1 error = ER_MASTER_INFO;
9555
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 my_message(ER_MASTER_INFO, ER_THD(thd, ER_MASTER_INFO), MYF(0));
9556 }
9557 }
9558 } else {
9559
1/2
✓ Branch 0 taken 3674 times.
✗ Branch 1 not taken.
3674 mi->channel_unlock();
9560 }
9561
9562 12602 err:
9563 12602 return error;
9564 12602 }
9565
9566 /**
9567 Entry function for RESET SLAVE command. Function either resets
9568 the slave for all channels or for a single channel.
9569 When RESET SLAVE ALL is given, the slave_info_objects (mi, rli & workers)
9570 are destroyed.
9571
9572 @param[in] thd the client thread with the command.
9573
9574 @retval false OK
9575 @retval true not OK
9576 */
9577 12914 bool reset_slave_cmd(THD *thd) {
9578
1/2
✓ Branch 0 taken 12914 times.
✗ Branch 1 not taken.
12914 DBUG_TRACE;
9579
9580 Master_info *mi;
9581 12914 LEX *lex = thd->lex;
9582 12914 bool res = true; // default, an error
9583
9584
1/2
✓ Branch 0 taken 12914 times.
✗ Branch 1 not taken.
12914 channel_map.wrlock();
9585
9586
3/4
✓ Branch 0 taken 12914 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 12912 times.
12914 if (!is_slave_configured()) {
9587
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_error(ER_SLAVE_CONFIGURATION, MYF(0));
9588
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 channel_map.unlock();
9589 2 return res = true;
9590 }
9591
9592
3/4
✓ Branch 0 taken 1321 times.
✓ Branch 1 taken 11591 times.
✓ Branch 2 taken 1321 times.
✗ Branch 3 not taken.
12912 if (!lex->mi.for_channel) res = reset_slave(thd);
9593 #ifdef WITH_WSREP
9594 // Similar to GR, do not allow operations on the wsrep channel
9595
6/8
✓ Branch 0 taken 11591 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11591 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 11589 times.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 11589 times.
11591 else if (lex->mi.channel && wsrep_is_wsrep_channel_name(lex->mi.channel)) {
9596
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_error(ER_SLAVE_CHANNEL_OPERATION_NOT_ALLOWED, MYF(0),
9597 "RESET SLAVE [ALL] FOR CHANNEL", lex->mi.channel);
9598
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 channel_map.unlock();
9599 2 return true;
9600 }
9601 #endif /* WITH_WSREP */
9602 else {
9603
1/2
✓ Branch 0 taken 11589 times.
✗ Branch 1 not taken.
11589 mi = channel_map.get_mi(lex->mi.channel);
9604 /*
9605 If the channel being used is a group replication channel and
9606 group_replication is still running we need to disable RESET SLAVE [ALL]
9607 command.
9608 */
9609 20159 if (mi &&
9610
3/4
✓ Branch 0 taken 8570 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 598 times.
✓ Branch 3 taken 7972 times.
8570 channel_map.is_group_replication_channel_name(mi->get_channel(),
9611
4/4
✓ Branch 0 taken 8570 times.
✓ Branch 1 taken 3019 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 11584 times.
20159 true) &&
9612
3/4
✓ Branch 0 taken 598 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 593 times.
598 is_group_replication_running()) {
9613
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 my_error(ER_SLAVE_CHANNEL_OPERATION_NOT_ALLOWED, MYF(0),
9614 "RESET SLAVE [ALL] FOR CHANNEL", mi->get_channel());
9615
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 channel_map.unlock();
9616 5 return true;
9617 }
9618
9619
2/2
✓ Branch 0 taken 8565 times.
✓ Branch 1 taken 3019 times.
11584 if (mi)
9620
1/2
✓ Branch 0 taken 8565 times.
✗ Branch 1 not taken.
8565 res = reset_slave(thd, mi, thd->lex->reset_slave_info.all);
9621
1/2
✓ Branch 0 taken 3019 times.
✗ Branch 1 not taken.
3019 else if (strcmp(channel_map.get_default_channel(), lex->mi.channel))
9622
1/2
✓ Branch 0 taken 3019 times.
✗ Branch 1 not taken.
3019 my_error(ER_SLAVE_CHANNEL_DOES_NOT_EXIST, MYF(0), lex->mi.channel);
9623 }
9624
9625
1/2
✓ Branch 0 taken 12905 times.
✗ Branch 1 not taken.
12905 channel_map.unlock();
9626
9627 12905 return res;
9628 12914 }
9629
9630 /**
9631 This function checks if the given CHANGE MASTER/REPLICATION SOURCE command
9632 has any receive option being set or changed.
9633
9634 - used in change_master().
9635
9636 @param lex_mi structure that holds all options given on the
9637 change replication source command.
9638
9639 @retval false No change replication source receive options were found.
9640 @retval true At least one receive option was found.
9641 */
9642 12652 static bool have_change_replication_source_receive_option(
9643 const LEX_MASTER_INFO *lex_mi) {
9644 12652 bool have_receive_option = false;
9645
9646
1/2
✓ Branch 0 taken 12652 times.
✗ Branch 1 not taken.
12652 DBUG_TRACE;
9647
9648 /* Check if *at least one* receive option is given the command*/
9649
6/6
✓ Branch 0 taken 4094 times.
✓ Branch 1 taken 8558 times.
✓ Branch 2 taken 2065 times.
✓ Branch 3 taken 2029 times.
✓ Branch 4 taken 2054 times.
✓ Branch 5 taken 11 times.
12652 if (lex_mi->host || lex_mi->user || lex_mi->password ||
9650
6/6
✓ Branch 0 taken 2021 times.
✓ Branch 1 taken 33 times.
✓ Branch 2 taken 2000 times.
✓ Branch 3 taken 21 times.
✓ Branch 4 taken 1986 times.
✓ Branch 5 taken 14 times.
2054 lex_mi->log_file_name || lex_mi->pos || lex_mi->bind_addr ||
9651
5/6
✓ Branch 0 taken 1986 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1953 times.
✓ Branch 3 taken 33 times.
✓ Branch 4 taken 1894 times.
✓ Branch 5 taken 59 times.
1986 lex_mi->network_namespace || lex_mi->port || lex_mi->connect_retry ||
9652
3/4
✓ Branch 0 taken 1894 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1868 times.
✓ Branch 3 taken 26 times.
1894 lex_mi->server_id || lex_mi->ssl != LEX_MASTER_INFO::LEX_MI_UNCHANGED ||
9653
2/2
✓ Branch 0 taken 1864 times.
✓ Branch 1 taken 4 times.
1868 lex_mi->ssl_verify_server_cert != LEX_MASTER_INFO::LEX_MI_UNCHANGED ||
9654
2/2
✓ Branch 0 taken 1822 times.
✓ Branch 1 taken 42 times.
1864 lex_mi->heartbeat_opt != LEX_MASTER_INFO::LEX_MI_UNCHANGED ||
9655
2/2
✓ Branch 0 taken 1785 times.
✓ Branch 1 taken 37 times.
1822 lex_mi->retry_count_opt != LEX_MASTER_INFO::LEX_MI_UNCHANGED ||
9656
6/6
✓ Branch 0 taken 1780 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 1776 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 1772 times.
✓ Branch 5 taken 4 times.
1785 lex_mi->ssl_key || lex_mi->ssl_cert || lex_mi->ssl_ca ||
9657
4/4
✓ Branch 0 taken 1770 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1768 times.
✓ Branch 3 taken 2 times.
1772 lex_mi->ssl_capath || lex_mi->tls_version ||
9658
2/2
✓ Branch 0 taken 1757 times.
✓ Branch 1 taken 11 times.
1768 lex_mi->tls_ciphersuites != LEX_MASTER_INFO::UNSPECIFIED ||
9659
6/6
✓ Branch 0 taken 1755 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1752 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 1750 times.
✓ Branch 5 taken 2 times.
1757 lex_mi->ssl_cipher || lex_mi->ssl_crl || lex_mi->ssl_crlpath ||
9660
2/2
✓ Branch 0 taken 1721 times.
✓ Branch 1 taken 29 times.
1750 lex_mi->repl_ignore_server_ids_opt == LEX_MASTER_INFO::LEX_MI_ENABLE ||
9661
2/2
✓ Branch 0 taken 1719 times.
✓ Branch 1 taken 2 times.
1721 lex_mi->public_key_path ||
9662
2/2
✓ Branch 0 taken 1717 times.
✓ Branch 1 taken 2 times.
1719 lex_mi->get_public_key != LEX_MASTER_INFO::LEX_MI_UNCHANGED ||
9663
4/4
✓ Branch 0 taken 1638 times.
✓ Branch 1 taken 79 times.
✓ Branch 2 taken 1555 times.
✓ Branch 3 taken 83 times.
1717 lex_mi->zstd_compression_level || lex_mi->compression_algorithm ||
9664
2/2
✓ Branch 0 taken 87 times.
✓ Branch 1 taken 1468 times.
1555 lex_mi->require_row_format != LEX_MASTER_INFO::LEX_MI_UNCHANGED)
9665 11184 have_receive_option = true;
9666
9667 12652 return have_receive_option;
9668 12652 }
9669
9670 /**
9671 This function checks if the given CHANGE MASTER/REPLICATION SOURCE command
9672 has any execute option being set or changed.
9673
9674 - used in change_master().
9675
9676 @param lex_mi structure that holds all options given on the
9677 change replication source command.
9678
9679 @param[out] need_relay_log_purge
9680 - If relay_log_file/relay_log_pos options are used,
9681 we won't delete relaylogs. We set this boolean flag to false.
9682 - If relay_log_file/relay_log_pos options are NOT used,
9683 we return the boolean flag UNCHANGED.
9684 - Used in change_receive_options() and change_master().
9685
9686 @retval false No change replication source execute option.
9687 @retval true At least one execute option was there.
9688 */
9689 12652 static bool have_change_replication_source_execute_option(
9690 const LEX_MASTER_INFO *lex_mi, bool *need_relay_log_purge) {
9691 12652 bool have_execute_option = false;
9692
9693
1/2
✓ Branch 0 taken 12652 times.
✗ Branch 1 not taken.
12652 DBUG_TRACE;
9694
9695 /* Check if *at least one* execute option is given on change master command*/
9696
4/4
✓ Branch 0 taken 12599 times.
✓ Branch 1 taken 53 times.
✓ Branch 2 taken 12593 times.
✓ Branch 3 taken 6 times.
12652 if (lex_mi->relay_log_name || lex_mi->relay_log_pos ||
9697
4/4
✓ Branch 0 taken 12496 times.
✓ Branch 1 taken 97 times.
✓ Branch 2 taken 12454 times.
✓ Branch 3 taken 42 times.
12593 lex_mi->sql_delay != -1 || lex_mi->privilege_checks_username != nullptr ||
9698
2/2
✓ Branch 0 taken 9657 times.
✓ Branch 1 taken 2797 times.
12454 lex_mi->privilege_checks_none ||
9699
2/2
✓ Branch 0 taken 9585 times.
✓ Branch 1 taken 72 times.
9657 lex_mi->require_row_format != LEX_MASTER_INFO::LEX_MI_UNCHANGED ||
9700
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 9564 times.
9585 lex_mi->require_table_primary_key_check !=
9701 LEX_MASTER_INFO::LEX_MI_PK_CHECK_UNCHANGED)
9702 3088 have_execute_option = true;
9703
9704
4/4
✓ Branch 0 taken 12599 times.
✓ Branch 1 taken 53 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 12593 times.
12652 if (lex_mi->relay_log_name || lex_mi->relay_log_pos)
9705 59 *need_relay_log_purge = false;
9706
9707 12652 return have_execute_option;
9708 12652 }
9709
9710 /**
9711 This function checks if the given CHANGE REPLICATION SOURCE command has
9712 any option that affect both the receiver and the applier.
9713
9714 - used in change_master().
9715
9716 @param lex_mi structure that holds all options given on the
9717 change replication source command.
9718
9719 @retval false no option that affects both applier and receiver was found
9720 @retval true At least one option affects both the applier and receiver.
9721 */
9722 12652 static bool have_change_replication_source_applier_and_receive_option(
9723 const LEX_MASTER_INFO *lex_mi) {
9724 12652 bool have_applier_receive_option = false;
9725
9726
1/2
✓ Branch 0 taken 12652 times.
✗ Branch 1 not taken.
12652 DBUG_TRACE;
9727
9728 /* Check if *at least one* receive option is given to change rep source*/
9729
2/2
✓ Branch 0 taken 12615 times.
✓ Branch 1 taken 37 times.
12652 if (lex_mi->assign_gtids_to_anonymous_transactions_type !=
9730 12615 LEX_MASTER_INFO::LEX_MI_ANONYMOUS_TO_GTID_UNCHANGED ||
9731
2/2
✓ Branch 0 taken 6887 times.
✓ Branch 1 taken 5728 times.
12615 lex_mi->auto_position != LEX_MASTER_INFO::LEX_MI_UNCHANGED ||
9732
2/2
✓ Branch 0 taken 6852 times.
✓ Branch 1 taken 35 times.
6887 lex_mi->m_source_connection_auto_failover !=
9733 6852 LEX_MASTER_INFO::LEX_MI_UNCHANGED ||
9734
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 6821 times.
6852 lex_mi->m_gtid_only != LEX_MASTER_INFO::LEX_MI_UNCHANGED)
9735 5831 have_applier_receive_option = true;
9736
9737 12652 return have_applier_receive_option;
9738 12652 }
9739
9740 /**
9741 This function checks all possible cases in which compression algorithm,
9742 compression level can be configured for a channel.
9743
9744 - used in change_receive_options
9745
9746 @param lex_mi pointer to structure holding all options specified
9747 as part of change master to statement
9748 @param mi pointer to structure holding all options specified
9749 as part of change master to statement after performing
9750 necessary checks
9751
9752 @retval false in case of success
9753 @retval true in case of failures
9754 */
9755 11129 static bool change_master_set_compression(THD *, const LEX_MASTER_INFO *lex_mi,
9756 Master_info *mi) {
9757
1/2
✓ Branch 0 taken 11129 times.
✗ Branch 1 not taken.
11129 DBUG_TRACE;
9758
9759
2/2
✓ Branch 0 taken 1502 times.
✓ Branch 1 taken 9627 times.
11129 if (lex_mi->compression_algorithm) {
9760
4/6
✓ Branch 0 taken 1502 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1502 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 27 times.
✓ Branch 5 taken 1475 times.
3004 if (validate_compression_attributes(lex_mi->compression_algorithm,
9761
1/2
✓ Branch 0 taken 1502 times.
✗ Branch 1 not taken.
1502 lex_mi->channel, false))
9762 27 return true;
9763
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1475 times.
1475 assert(sizeof(mi->compression_algorithm) >
9764 strlen(lex_mi->compression_algorithm));
9765 1475 strcpy(mi->compression_algorithm, lex_mi->compression_algorithm);
9766 }
9767 /* level specified */
9768
2/2
✓ Branch 0 taken 1462 times.
✓ Branch 1 taken 9640 times.
11102 if (lex_mi->zstd_compression_level) {
9769 /* vaildate compression level */
9770
3/4
✓ Branch 0 taken 1462 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 1453 times.
1462 if (!is_zstd_compression_level_valid(lex_mi->zstd_compression_level)) {
9771 9 my_error(ER_CHANGE_MASTER_WRONG_COMPRESSION_LEVEL_CLIENT, MYF(0),
9772
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 lex_mi->zstd_compression_level, lex_mi->channel);
9773 9 return true;
9774 }
9775 1453 mi->zstd_compression_level = lex_mi->zstd_compression_level;
9776 }
9777 11093 return false;
9778 11129 }
9779
9780 /**
9781 This function is called if the change master command had at least one
9782 receive option. This function then sets or alters the receive option(s)
9783 given in the command. The execute options are handled in the function
9784 change_execute_options()
9785
9786 - used in change_master().
9787 - Receiver threads should be stopped when this function is called.
9788
9789 @param thd Pointer to THD object for the client thread executing the
9790 statement.
9791
9792 @param lex_mi structure that holds all change master options given on the
9793 change master command.
9794 Coming from the an executing statement or set directly this
9795 shall contain connection settings like hostname, user, password
9796 and other settings like the number of connection retries.
9797
9798 @param mi Pointer to Master_info object belonging to the replica channel
9799 to be configured
9800
9801 @retval 0 no error i.e., success.
9802 @retval !=0 error.
9803 */
9804 11130 static int change_receive_options(THD *thd, LEX_MASTER_INFO *lex_mi,
9805 Master_info *mi) {
9806 11130 int ret = 0; /* return value. Set if there is an error. */
9807
9808
1/2
✓ Branch 0 taken 11130 times.
✗ Branch 1 not taken.
11130 DBUG_TRACE;
9809
9810 /*
9811 If the user specified host or port without binlog or position,
9812 reset binlog's name to FIRST and position to 4.
9813 */
9814
9815
4/4
✓ Branch 0 taken 8547 times.
✓ Branch 1 taken 2583 times.
✓ Branch 2 taken 933 times.
✓ Branch 3 taken 7614 times.
11130 if ((lex_mi->host && strcmp(lex_mi->host, mi->host)) ||
9816
4/4
✓ Branch 0 taken 264 times.
✓ Branch 1 taken 3252 times.
✓ Branch 2 taken 96 times.
✓ Branch 3 taken 168 times.
3516 (lex_mi->port && lex_mi->port != mi->port)) {
9817 /*
9818 This is necessary because the primary key, i.e. host or port, has
9819 changed.
9820
9821 The repository does not support direct changes on the primary key,
9822 so the row is dropped and re-inserted with a new primary key. If we
9823 don't do that, the master info repository we will end up with several
9824 rows.
9825 */
9826
2/4
✓ Branch 0 taken 7710 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7710 times.
7710 if (mi->clean_info()) {
9827 ret = 1;
9828 goto err;
9829 }
9830 7710 mi->master_uuid[0] = 0;
9831 7710 mi->master_id = 0;
9832 }
9833
9834
6/6
✓ Branch 0 taken 2583 times.
✓ Branch 1 taken 8547 times.
✓ Branch 2 taken 32 times.
✓ Branch 3 taken 2551 times.
✓ Branch 4 taken 8541 times.
✓ Branch 5 taken 38 times.
11130 if ((lex_mi->host || lex_mi->port) && !lex_mi->log_file_name &&
9835
2/2
✓ Branch 0 taken 8534 times.
✓ Branch 1 taken 7 times.
8541 !lex_mi->pos) {
9836 8534 char *var_master_log_name = nullptr;
9837 8534 var_master_log_name = const_cast<char *>(mi->get_master_log_name());
9838 8534 var_master_log_name[0] = '\0';
9839 8534 mi->set_master_log_pos(BIN_LOG_HEADER_SIZE);
9840 }
9841
9842
3/4
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 11064 times.
✓ Branch 2 taken 66 times.
✗ Branch 3 not taken.
11130 if (lex_mi->log_file_name) mi->set_master_log_name(lex_mi->log_file_name);
9843
2/2
✓ Branch 0 taken 73 times.
✓ Branch 1 taken 11057 times.
11130 if (lex_mi->pos) {
9844 73 mi->set_master_log_pos(lex_mi->pos);
9845 }
9846
9847
4/4
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 11064 times.
✓ Branch 2 taken 19 times.
✓ Branch 3 taken 47 times.
11130 if (lex_mi->log_file_name && !lex_mi->pos)
9848
2/4
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19 times.
✗ Branch 3 not taken.
19 push_warning(thd, Sql_condition::SL_WARNING,
9849 ER_WARN_ONLY_MASTER_LOG_FILE_NO_POS,
9850 ER_THD(thd, ER_WARN_ONLY_MASTER_LOG_FILE_NO_POS));
9851
9852
3/8
✓ Branch 0 taken 11130 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11130 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 11130 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
11130 DBUG_PRINT("info", ("master_log_pos: %lu", (ulong)mi->get_master_log_pos()));
9853
9854
4/4
✓ Branch 0 taken 5652 times.
✓ Branch 1 taken 5478 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 5643 times.
11130 if (lex_mi->user || lex_mi->password) {
9855
3/4
✓ Branch 0 taken 5487 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5481 times.
✓ Branch 3 taken 6 times.
5487 if (!thd->get_ssl()) {
9856
2/4
✓ Branch 0 taken 5481 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5481 times.
✗ Branch 3 not taken.
5481 push_warning(thd, Sql_condition::SL_NOTE, ER_INSECURE_PLAIN_TEXT,
9857 ER_THD(thd, ER_INSECURE_PLAIN_TEXT));
9858 }
9859
2/4
✓ Branch 0 taken 5487 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5487 times.
✗ Branch 3 not taken.
5487 push_warning(thd, Sql_condition::SL_NOTE, ER_INSECURE_CHANGE_MASTER,
9860 ER_THD(thd, ER_INSECURE_CHANGE_MASTER));
9861 }
9862
9863
3/4
✓ Branch 0 taken 5478 times.
✓ Branch 1 taken 5652 times.
✓ Branch 2 taken 5478 times.
✗ Branch 3 not taken.
11130 if (lex_mi->user) mi->set_user(lex_mi->user);
9864
3/4
✓ Branch 0 taken 193 times.
✓ Branch 1 taken 10937 times.
✓ Branch 2 taken 193 times.
✗ Branch 3 not taken.
11130 if (lex_mi->password) mi->set_password(lex_mi->password);
9865
3/4
✓ Branch 0 taken 8547 times.
✓ Branch 1 taken 2583 times.
✓ Branch 2 taken 8547 times.
✗ Branch 3 not taken.
11130 if (lex_mi->host) strmake(mi->host, lex_mi->host, sizeof(mi->host) - 1);
9866
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 11106 times.
11130 if (lex_mi->bind_addr)
9867
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 strmake(mi->bind_addr, lex_mi->bind_addr, sizeof(mi->bind_addr) - 1);
9868
9869
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 11127 times.
11130 if (lex_mi->network_namespace)
9870
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 strmake(mi->network_namespace, lex_mi->network_namespace,
9871 sizeof(mi->network_namespace) - 1);
9872 /*
9873 Setting channel's port number explicitly to '0' should be allowed.
9874 Eg: 'group_replication_recovery' channel (*after recovery is done*)
9875 or 'group_replication_applier' channel wants to set the port number
9876 to '0' as there is no actual network usage on these channels.
9877 */
9878
4/4
✓ Branch 0 taken 6254 times.
✓ Branch 1 taken 4876 times.
✓ Branch 2 taken 3492 times.
✓ Branch 3 taken 2762 times.
11130 if (lex_mi->port || lex_mi->port_opt == LEX_MASTER_INFO::LEX_MI_ENABLE)
9879 8368 mi->port = lex_mi->port;
9880
2/2
✓ Branch 0 taken 3011 times.
✓ Branch 1 taken 8119 times.
11130 if (lex_mi->connect_retry) mi->connect_retry = lex_mi->connect_retry;
9881
2/2
✓ Branch 0 taken 2797 times.
✓ Branch 1 taken 8333 times.
11130 if (lex_mi->retry_count_opt != LEX_MASTER_INFO::LEX_MI_UNCHANGED)
9882 2797 mi->retry_count = lex_mi->retry_count;
9883
9884
2/2
✓ Branch 0 taken 79 times.
✓ Branch 1 taken 11051 times.
11130 if (lex_mi->heartbeat_opt != LEX_MASTER_INFO::LEX_MI_UNCHANGED)
9885 79 mi->heartbeat_period = lex_mi->heartbeat_period;
9886
4/4
✓ Branch 0 taken 2542 times.
✓ Branch 1 taken 8509 times.
✓ Branch 2 taken 32 times.
✓ Branch 3 taken 2510 times.
11051 else if (lex_mi->host || lex_mi->port) {
9887 /*
9888 If the user specified host or port or both without heartbeat_period,
9889 we use default value for heartbeat_period. By default, We want to always
9890 have heartbeat enabled when we switch master unless
9891 master_heartbeat_period is explicitly set to zero (heartbeat disabled).
9892
9893 Here is the default value for heartbeat period if CHANGE MASTER did not
9894 specify it. (no data loss in conversion as hb period has a max)
9895 */
9896 17082 mi->heartbeat_period = std::min<float>(SLAVE_MAX_HEARTBEAT_PERIOD,
9897 8541 (replica_net_timeout / 2.0f));
9898
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8541 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
8541 assert(mi->heartbeat_period > (float)0.001 || mi->heartbeat_period == 0);
9899
9900 // counter is cleared if master is CHANGED.
9901 8541 mi->received_heartbeats = 0;
9902 // clear timestamp of last heartbeat as well.
9903 8541 mi->last_heartbeat = 0;
9904 }
9905
9906 /*
9907 reset the last time server_id list if the current CHANGE MASTER
9908 is mentioning IGNORE_SERVER_IDS= (...)
9909 */
9910
2/2
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 11093 times.
11130 if (lex_mi->repl_ignore_server_ids_opt == LEX_MASTER_INFO::LEX_MI_ENABLE)
9911
1/2
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
37 mi->ignore_server_ids->dynamic_ids.clear();
9912
3/4
✓ Branch 0 taken 11220 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 91 times.
✓ Branch 3 taken 11129 times.
11220 for (size_t i = 0; i < lex_mi->repl_ignore_server_ids.size(); i++) {
9913
1/2
✓ Branch 0 taken 91 times.
✗ Branch 1 not taken.
91 ulong s_id = lex_mi->repl_ignore_server_ids[i];
9914
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 90 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
91 if (s_id == ::server_id && replicate_same_server_id) {
9915 1 ret = ER_SLAVE_IGNORE_SERVER_IDS;
9916
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_SLAVE_IGNORE_SERVER_IDS, MYF(0), static_cast<int>(s_id));
9917 1 goto err;
9918 } else {
9919 // Keep the array sorted, ignore duplicates.
9920
1/2
✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
90 mi->ignore_server_ids->dynamic_ids.insert_unique(s_id);
9921 }
9922 }
9923
9924
2/2
✓ Branch 0 taken 1420 times.
✓ Branch 1 taken 9709 times.
11129 if (lex_mi->ssl != LEX_MASTER_INFO::LEX_MI_UNCHANGED)
9925 1420 mi->ssl = (lex_mi->ssl == LEX_MASTER_INFO::LEX_MI_ENABLE);
9926
9927
2/2
✓ Branch 0 taken 1350 times.
✓ Branch 1 taken 9779 times.
11129 if (lex_mi->ssl_verify_server_cert != LEX_MASTER_INFO::LEX_MI_UNCHANGED)
9928 1350 mi->ssl_verify_server_cert =
9929 1350 (lex_mi->ssl_verify_server_cert == LEX_MASTER_INFO::LEX_MI_ENABLE);
9930
9931
2/2
✓ Branch 0 taken 1355 times.
✓ Branch 1 taken 9774 times.
11129 if (lex_mi->public_key_path)
9932
1/2
✓ Branch 0 taken 1355 times.
✗ Branch 1 not taken.
1355 strmake(mi->public_key_path, lex_mi->public_key_path,
9933 sizeof(mi->public_key_path) - 1);
9934
9935
2/2
✓ Branch 0 taken 2493 times.
✓ Branch 1 taken 8636 times.
11129 if (lex_mi->get_public_key != LEX_MASTER_INFO::LEX_MI_UNCHANGED)
9936 2493 mi->get_public_key =
9937 2493 (lex_mi->get_public_key == LEX_MASTER_INFO::LEX_MI_ENABLE);
9938
9939
2/2
✓ Branch 0 taken 1370 times.
✓ Branch 1 taken 9759 times.
11129 if (lex_mi->ssl_ca)
9940
1/2
✓ Branch 0 taken 1370 times.
✗ Branch 1 not taken.
1370 strmake(mi->ssl_ca, lex_mi->ssl_ca, sizeof(mi->ssl_ca) - 1);
9941
2/2
✓ Branch 0 taken 1341 times.
✓ Branch 1 taken 9788 times.
11129 if (lex_mi->ssl_capath)
9942
1/2
✓ Branch 0 taken 1341 times.
✗ Branch 1 not taken.
1341 strmake(mi->ssl_capath, lex_mi->ssl_capath, sizeof(mi->ssl_capath) - 1);
9943
2/2
✓ Branch 0 taken 1347 times.
✓ Branch 1 taken 9782 times.
11129 if (lex_mi->tls_version)
9944
1/2
✓ Branch 0 taken 1347 times.
✗ Branch 1 not taken.
1347 strmake(mi->tls_version, lex_mi->tls_version, sizeof(mi->tls_version) - 1);
9945
9946
2/2
✓ Branch 0 taken 1334 times.
✓ Branch 1 taken 9795 times.
11129 if (LEX_MASTER_INFO::SPECIFIED_NULL == lex_mi->tls_ciphersuites) {
9947 1334 mi->tls_ciphersuites.first = true;
9948 1334 mi->tls_ciphersuites.second.clear();
9949
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 9775 times.
9795 } else if (LEX_MASTER_INFO::SPECIFIED_STRING == lex_mi->tls_ciphersuites) {
9950 20 mi->tls_ciphersuites.first = false;
9951
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 mi->tls_ciphersuites.second.assign(lex_mi->tls_ciphersuites_string);
9952 }
9953
9954
2/2
✓ Branch 0 taken 1370 times.
✓ Branch 1 taken 9759 times.
11129 if (lex_mi->ssl_cert)
9955
1/2
✓ Branch 0 taken 1370 times.
✗ Branch 1 not taken.
1370 strmake(mi->ssl_cert, lex_mi->ssl_cert, sizeof(mi->ssl_cert) - 1);
9956
2/2
✓ Branch 0 taken 1341 times.
✓ Branch 1 taken 9788 times.
11129 if (lex_mi->ssl_cipher)
9957
1/2
✓ Branch 0 taken 1341 times.
✗ Branch 1 not taken.
1341 strmake(mi->ssl_cipher, lex_mi->ssl_cipher, sizeof(mi->ssl_cipher) - 1);
9958
2/2
✓ Branch 0 taken 1370 times.
✓ Branch 1 taken 9759 times.
11129 if (lex_mi->ssl_key)
9959
1/2
✓ Branch 0 taken 1370 times.
✗ Branch 1 not taken.
1370 strmake(mi->ssl_key, lex_mi->ssl_key, sizeof(mi->ssl_key) - 1);
9960
2/2
✓ Branch 0 taken 1352 times.
✓ Branch 1 taken 9777 times.
11129 if (lex_mi->ssl_crl)
9961
1/2
✓ Branch 0 taken 1352 times.
✗ Branch 1 not taken.
1352 strmake(mi->ssl_crl, lex_mi->ssl_crl, sizeof(mi->ssl_crl) - 1);
9962
2/2
✓ Branch 0 taken 1352 times.
✓ Branch 1 taken 9777 times.
11129 if (lex_mi->ssl_crlpath)
9963
1/2
✓ Branch 0 taken 1352 times.
✗ Branch 1 not taken.
1352 strmake(mi->ssl_crlpath, lex_mi->ssl_crlpath, sizeof(mi->ssl_crlpath) - 1);
9964
9965
1/2
✓ Branch 0 taken 11129 times.
✗ Branch 1 not taken.
11129 ret = change_master_set_compression(thd, lex_mi, mi);
9966
2/2
✓ Branch 0 taken 11093 times.
✓ Branch 1 taken 36 times.
11129 if (ret) goto err;
9967
9968 11093 err:
9969 11130 return ret;
9970 11130 }
9971
9972 /**
9973 This function is called if the change master command had at least one
9974 execute option. This function then sets or alters the execute option(s)
9975 given in the command. The receive options are handled in the function
9976 change_receive_options()
9977
9978 - used in change_master().
9979 - Execute threads should be stopped before this function is called.
9980
9981 @param lex_mi structure that holds all change master options given on the
9982 change master command.
9983
9984 @param mi Pointer to Master_info object belonging to the replica channel
9985 that will be configured
9986
9987 @return false if the execute options were successfully set and true,
9988 otherwise.
9989 */
9990 3051 static bool change_execute_options(LEX_MASTER_INFO *lex_mi, Master_info *mi) {
9991
1/2
✓ Branch 0 taken 3051 times.
✗ Branch 1 not taken.
3051 DBUG_TRACE;
9992
9993
2/2
✓ Branch 0 taken 3011 times.
✓ Branch 1 taken 40 times.
3051 if (lex_mi->privilege_checks_username != nullptr ||
9994
2/2
✓ Branch 0 taken 2797 times.
✓ Branch 1 taken 214 times.
3011 lex_mi->privilege_checks_none) {
9995 Relay_log_info::enum_priv_checks_status error{
9996
1/2
✓ Branch 0 taken 2837 times.
✗ Branch 1 not taken.
2837 mi->rli->set_privilege_checks_user(
9997 lex_mi->privilege_checks_username,
9998
2/2
✓ Branch 0 taken 2797 times.
✓ Branch 1 taken 40 times.
2837 lex_mi->privilege_checks_none ? nullptr
9999 : lex_mi->privilege_checks_hostname)};
10000
2/4
✓ Branch 0 taken 2837 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2837 times.
2837 if (!!error) {
10001 mi->rli->report_privilege_check_error(
10002 ERROR_LEVEL, error, true /* to client*/, mi->rli->get_channel(),
10003 lex_mi->privilege_checks_username, lex_mi->privilege_checks_hostname);
10004 return true;
10005 }
10006 }
10007
10008
2/2
✓ Branch 0 taken 2848 times.
✓ Branch 1 taken 203 times.
3051 if (lex_mi->require_row_format != LEX_MASTER_INFO::LEX_MI_UNCHANGED) {
10009
1/2
✓ Branch 0 taken 2848 times.
✗ Branch 1 not taken.
2848 mi->rli->set_require_row_format(lex_mi->require_row_format ==
10010 LEX_MASTER_INFO::LEX_MI_ENABLE);
10011 }
10012
10013
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 3026 times.
3051 if (lex_mi->require_table_primary_key_check !=
10014 LEX_MASTER_INFO::LEX_MI_PK_CHECK_UNCHANGED) {
10015
3/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
25 switch (lex_mi->require_table_primary_key_check) {
10016 5 case (LEX_MASTER_INFO::LEX_MI_PK_CHECK_STREAM):
10017
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 mi->rli->set_require_table_primary_key_check(
10018 Relay_log_info::PK_CHECK_STREAM);
10019 5 break;
10020 8 case (LEX_MASTER_INFO::LEX_MI_PK_CHECK_ON):
10021
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 mi->rli->set_require_table_primary_key_check(
10022 Relay_log_info::PK_CHECK_ON);
10023 8 break;
10024 12 case (LEX_MASTER_INFO::LEX_MI_PK_CHECK_OFF):
10025
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 mi->rli->set_require_table_primary_key_check(
10026 Relay_log_info::PK_CHECK_OFF);
10027 12 break;
10028
10029 default: /* purecov: tested */
10030 assert(0); /* purecov: tested */
10031 break;
10032 }
10033 }
10034
10035
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 3001 times.
3051 if (lex_mi->relay_log_name) {
10036 char relay_log_name[FN_REFLEN];
10037
1/2
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
50 mi->rli->relay_log.make_log_name(relay_log_name, lex_mi->relay_log_name);
10038
1/2
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
50 mi->rli->set_group_relay_log_name(relay_log_name);
10039 50 mi->rli->is_group_master_log_pos_invalid = true;
10040 }
10041
10042
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 3015 times.
3051 if (lex_mi->relay_log_pos) {
10043 36 mi->rli->set_group_relay_log_pos(lex_mi->relay_log_pos);
10044 36 mi->rli->is_group_master_log_pos_invalid = true;
10045 }
10046
10047
2/2
✓ Branch 0 taken 82 times.
✓ Branch 1 taken 2969 times.
3051 if (lex_mi->sql_delay != -1) mi->rli->set_sql_delay(lex_mi->sql_delay);
10048
10049 3051 return false;
10050 3051 }
10051
10052 /**
10053 This function is called if the change replication source command had at
10054 least one option that affects both the receiver and applier parts.
10055 Pure execute option(s) are handled in change_execute_options()
10056 The receive options are handled in the function change_receive_options()
10057
10058 - used in change_master().
10059 - Both receiver and applier threads should be stopped on invocation
10060
10061 @param lex_mi structure that holds all change replication source options
10062
10063 @param mi Pointer to Master_info object belonging to the replica channel
10064 to be configured
10065
10066 @return false if successfully set, true otherwise.
10067 */
10068 5781 static bool change_applier_receiver_options(THD *thd, LEX_MASTER_INFO *lex_mi,
10069 Master_info *mi) {
10070
2/2
✓ Branch 0 taken 98 times.
✓ Branch 1 taken 5683 times.
5781 if (lex_mi->m_source_connection_auto_failover !=
10071 LEX_MASTER_INFO::LEX_MI_UNCHANGED) {
10072
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 18 times.
98 if (lex_mi->m_source_connection_auto_failover ==
10073 LEX_MASTER_INFO::LEX_MI_ENABLE) {
10074 80 mi->set_source_connection_auto_failover();
10075 /*
10076 Send replication channel SOURCE_CONNECTION_AUTO_FAILOVER attribute of
10077 CHANGE REPLICATION SOURCE command status to group replication group
10078 members.
10079 */
10080
3/6
✓ Branch 0 taken 80 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 80 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 80 times.
160 if (rpl_acf_configuration_handler->send_channel_status_and_version_data(
10081 80 mi->get_channel(),
10082 Rpl_acf_status_configuration::SOURCE_CONNECTION_AUTO_FAILOVER,
10083 1)) {
10084 my_error(ER_GRP_RPL_FAILOVER_CHANNEL_STATUS_PROPAGATION, MYF(0),
10085 mi->get_channel());
10086 mi->unset_source_connection_auto_failover();
10087 return true;
10088 }
10089
10090 /*
10091 If IO thread is running and the monitoring thread is not, start
10092 the monitoring thread.
10093 */
10094
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 80 times.
80 if (mi->slave_running &&
10095
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
80 !Source_IO_monitor::get_instance()->is_monitoring_process_running()) {
10096 if (Source_IO_monitor::get_instance()->launch_monitoring_process(
10097 key_thread_replica_monitor_io)) {
10098 my_error(ER_STARTING_REPLICA_MONITOR_IO_THREAD, MYF(0));
10099 return true;
10100 }
10101 }
10102 } else {
10103 /*
10104 If this is the only channel with source_connection_auto_failover,
10105 then stop the monitoring thread.
10106 */
10107
4/6
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 18 times.
18 if (mi->is_source_connection_auto_failover() && mi->slave_running &&
10108 channel_map
10109 .get_number_of_connection_auto_failover_channels_running() ==
10110 1) {
10111 if (Source_IO_monitor::get_instance()->terminate_monitoring_process()) {
10112 my_error(ER_STOP_REPLICA_MONITOR_IO_THREAD_TIMEOUT, MYF(0));
10113 return true;
10114 }
10115 }
10116 18 mi->unset_source_connection_auto_failover();
10117 /*
10118 Send replication channel SOURCE_CONNECTION_AUTO_FAILOVER attribute of
10119 CHANGE REPLICATION SOURCE command status to group replication group
10120 members.
10121 */
10122
3/6
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 18 times.
36 if (rpl_acf_configuration_handler->send_channel_status_and_version_data(
10123 18 mi->get_channel(),
10124 Rpl_acf_status_configuration::SOURCE_CONNECTION_AUTO_FAILOVER,
10125 0)) {
10126 my_error(ER_GRP_RPL_FAILOVER_CHANNEL_STATUS_PROPAGATION, MYF(0),
10127 mi->get_channel());
10128 return true;
10129 }
10130 }
10131 }
10132
10133
2/2
✓ Branch 0 taken 5700 times.
✓ Branch 1 taken 81 times.
5781 if (lex_mi->auto_position != LEX_MASTER_INFO::LEX_MI_UNCHANGED) {
10134 5700 mi->set_auto_position(
10135 5700 (lex_mi->auto_position == LEX_MASTER_INFO::LEX_MI_ENABLE));
10136 }
10137
10138
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 5752 times.
5781 if (lex_mi->assign_gtids_to_anonymous_transactions_type !=
10139 LEX_MASTER_INFO::LEX_MI_ANONYMOUS_TO_GTID_UNCHANGED) {
10140
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 11 times.
29 if (lex_mi->assign_gtids_to_anonymous_transactions_type >
10141 LEX_MASTER_INFO::LEX_MI_ANONYMOUS_TO_GTID_OFF) {
10142 18 push_warning(
10143 thd, Sql_condition::SL_NOTE,
10144 ER_USING_ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS_AS_LOCAL_OR_UUID,
10145 ER_THD(
10146 thd,
10147 ER_USING_ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS_AS_LOCAL_OR_UUID));
10148 }
10149
10150
3/4
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
29 switch (lex_mi->assign_gtids_to_anonymous_transactions_type) {
10151 12 case (LEX_MASTER_INFO::LEX_MI_ANONYMOUS_TO_GTID_LOCAL):
10152 12 mi->rli->m_assign_gtids_to_anonymous_transactions_info.set_info(
10153 Assign_gtids_to_anonymous_transactions_info::enum_type::AGAT_LOCAL,
10154 ::server_uuid);
10155 12 break;
10156 6 case (LEX_MASTER_INFO::LEX_MI_ANONYMOUS_TO_GTID_UUID):
10157
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (mi->rli->m_assign_gtids_to_anonymous_transactions_info.set_info(
10158 Assign_gtids_to_anonymous_transactions_info::enum_type::
10159 AGAT_UUID,
10160 lex_mi->assign_gtids_to_anonymous_transactions_manual_uuid))
10161 return true;
10162 6 break;
10163 11 case (LEX_MASTER_INFO::LEX_MI_ANONYMOUS_TO_GTID_OFF):
10164 11 mi->rli->m_assign_gtids_to_anonymous_transactions_info.set_info(
10165 Assign_gtids_to_anonymous_transactions_info::enum_type::AGAT_OFF,
10166 "");
10167 11 break;
10168 default:
10169 assert(0);
10170 break;
10171 }
10172 }
10173
10174
2/2
✓ Branch 0 taken 2799 times.
✓ Branch 1 taken 2982 times.
5781 if (lex_mi->m_gtid_only != LEX_MASTER_INFO::LEX_MI_UNCHANGED) {
10175 2799 mi->set_gtid_only_mode(
10176 2799 (lex_mi->m_gtid_only == LEX_MASTER_INFO::LEX_MI_ENABLE));
10177 }
10178
10179 5781 return false;
10180 }
10181
10182 /**
10183 This function shall issue a deprecation warning if
10184 there are server ids tokenized from the CHANGE MASTER
10185 TO command while @@global.gtid_mode=ON.
10186 */
10187 7667 static void issue_deprecation_warnings_for_channel(THD *thd) {
10188 7667 LEX_MASTER_INFO *lex_mi = &thd->lex->mi;
10189
10190 /*
10191 Deprecation of GTID_MODE + IGNORE_SERVER_IDS
10192
10193 Generate deprecation warning when user executes CHANGE
10194 MASTER TO IGNORE_SERVER_IDS if GTID_MODE=ON.
10195 */
10196
4/4
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 7643 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 7665 times.
7691 if (lex_mi->repl_ignore_server_ids.size() > 0 &&
10197
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 22 times.
24 global_gtid_mode.get() == Gtid_mode::ON) {
10198 2 push_warning_printf(thd, Sql_condition::SL_WARNING,
10199 ER_WARN_DEPRECATED_SYNTAX,
10200 ER_THD(thd, ER_WARN_DEPRECATED_SYNTAX_NO_REPLACEMENT),
10201 "CHANGE MASTER TO ... IGNORE_SERVER_IDS='...' "
10202 "(when @@GLOBAL.GTID_MODE = ON)");
10203 }
10204 7667 }
10205
10206 /**
10207 This function validates that change replication source options are
10208 valid according to the current GTID_MODE.
10209 This method assumes it will only be called when GTID_MODE != ON
10210
10211 @param lex_mi structure that holds all change replication source options
10212
10213 @param mi Pointer to Master_info object belonging to the replica channel
10214 to be configured
10215
10216 @return false if the configuration is valid
10217 true some configuration option is invalid with GTID_MODE
10218 */
10219 3248 static int validate_gtid_option_restrictions(const LEX_MASTER_INFO *lex_mi,
10220 Master_info *mi) {
10221 3248 int error = 0;
10222
10223 /*
10224 CHANGE REPLICATION SOURCE TO SOURCE_AUTO_POSITION = 1 requires
10225 GTID_MODE != OFF
10226 */
10227
2/2
✓ Branch 0 taken 3187 times.
✓ Branch 1 taken 61 times.
3248 if (global_gtid_mode.get() == Gtid_mode::OFF) {
10228
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 3175 times.
3187 if (lex_mi->auto_position == LEX_MASTER_INFO::LEX_MI_ENABLE) {
10229 12 error = ER_AUTO_POSITION_REQUIRES_GTID_MODE_NOT_OFF;
10230 12 my_error(ER_AUTO_POSITION_REQUIRES_GTID_MODE_NOT_OFF, MYF(0));
10231 12 return error;
10232 }
10233 }
10234
10235 /*
10236 CHANGE REPLICATION SOURCE TO ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS != OFF
10237 requires GTID_MODE = ON
10238 */
10239
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3235 times.
3236 if (lex_mi->assign_gtids_to_anonymous_transactions_type >
10240 LEX_MASTER_INFO::LEX_MI_ANONYMOUS_TO_GTID_OFF) {
10241 1 error = ER_ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS_REQUIRES_GTID_MODE_ON;
10242 1 my_error(ER_ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS_REQUIRES_GTID_MODE_ON,
10243 MYF(0));
10244 1 return error;
10245 }
10246
10247 /*
10248 CHANGE REPLICATION SOURCE TO GTID_ONLY= 1 requires
10249 GTID_MODE = ON
10250 */
10251
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3234 times.
3235 if (lex_mi->m_gtid_only == LEX_MASTER_INFO::LEX_MI_ENABLE) {
10252 1 error = ER_CHANGE_REPLICATION_SOURCE_NO_OPTIONS_FOR_GTID_ONLY;
10253 1 my_error(ER_CHANGE_REPLICATION_SOURCE_NO_OPTIONS_FOR_GTID_ONLY, MYF(0),
10254 mi->get_channel());
10255 1 return error;
10256 }
10257
10258 /*
10259 CHANGE REPLICATION SOURCE TO SOURCE_CONNECTION_AUTO_FAILOVER = 1 requires
10260 GTID_MODE = ON
10261 */
10262
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3231 times.
3234 if (lex_mi->m_source_connection_auto_failover ==
10263 LEX_MASTER_INFO::LEX_MI_ENABLE) {
10264 3 error = ER_RPL_ASYNC_RECONNECT_GTID_MODE_OFF;
10265 3 my_error(ER_RPL_ASYNC_RECONNECT_GTID_MODE_OFF, MYF(0));
10266 3 return error;
10267 }
10268
10269
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3229 times.
3231 if (channel_map.is_group_replication_channel_name(lex_mi->channel)) {
10270 2 error = ER_CHANGE_REP_SOURCE_GR_CHANNEL_WITH_GTID_MODE_NOT_ON;
10271 2 my_error(error, MYF(0));
10272 2 return error;
10273 }
10274
10275 3229 return error;
10276 }
10277
10278 /**
10279 This is an helper method for boolean vars like
10280 SOURCE_AUTO_POSITION
10281 REQUIRE_ROW_FORMAT
10282 SOURCE_CONNECTION_AUTO_FAILOVER
10283 It tells if the variable is already enabled or will be by the command
10284
10285 @param base_value the current variable value
10286 @param option_value the configuration input value (UNCHANGED,ENABLED,DISABLE)
10287
10288 @return true if the option was already enable or will be. false otherwise
10289 */
10290 50312 bool is_option_enabled_or_will_be(bool base_value, int option_value) {
10291 50312 bool var_enabled = base_value;
10292
3/4
✓ Branch 0 taken 3028 times.
✓ Branch 1 taken 8446 times.
✓ Branch 2 taken 38838 times.
✗ Branch 3 not taken.
50312 switch (option_value) {
10293 3028 case LEX_MASTER_INFO::LEX_MI_ENABLE:
10294 3028 var_enabled = true;
10295 3028 break;
10296 8446 case LEX_MASTER_INFO::LEX_MI_DISABLE:
10297 8446 var_enabled = false;
10298 8446 break;
10299 38838 case LEX_MASTER_INFO::LEX_MI_UNCHANGED:
10300 38838 break;
10301 default:
10302 assert(0);
10303 break;
10304 }
10305 50312 return var_enabled;
10306 }
10307
10308 /**
10309 This method evaluates if the different options given to
10310 CHANGE REPLICATION SOURCE TO
10311 are compatible with the current configuration and with one another.
10312
10313 Example: SOURCE_CONNECTION_AUTO_FAILOVER = 1 requires
10314 SOURCE_AUTO_POSITION to be already enabled or to be enabled on this command.
10315
10316 @param lex_mi structure that holds all change replication source options given
10317 on the command
10318
10319 @param mi Pointer to Master_info object for the channel that holds the
10320 the configuration
10321
10322 @return 0 if no issues are found
10323 != 0 the error number associated to the issue, if one is found
10324 */
10325 12578 int evaluate_inter_option_dependencies(const LEX_MASTER_INFO *lex_mi,
10326 Master_info *mi) {
10327 12578 int error = 0;
10328
10329 /**
10330 We first define the variables used and then we group the checks for
10331 readability
10332 */
10333 12578 bool is_or_will_auto_position_be_enabled = is_option_enabled_or_will_be(
10334 12578 mi->is_auto_position(), lex_mi->auto_position);
10335 bool will_auto_position_be_disable =
10336
2/2
✓ Branch 0 taken 4576 times.
✓ Branch 1 taken 8002 times.
17154 mi->is_auto_position() &&
10337
2/2
✓ Branch 0 taken 1121 times.
✓ Branch 1 taken 3455 times.
4576 lex_mi->auto_position == LEX_MASTER_INFO::LEX_MI_DISABLE;
10338
10339 25156 bool is_or_will_require_row_format_be_enabled = is_option_enabled_or_will_be(
10340 12578 mi->rli->is_row_format_required(), lex_mi->require_row_format);
10341 bool will_require_row_format_be_disable =
10342
2/2
✓ Branch 0 taken 3356 times.
✓ Branch 1 taken 9222 times.
15934 mi->rli->is_row_format_required() &&
10343
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 3324 times.
3356 lex_mi->require_row_format == LEX_MASTER_INFO::LEX_MI_DISABLE;
10344
10345 bool is_or_will_source_connection_auto_failover_be_enabled =
10346 12578 is_option_enabled_or_will_be(mi->is_source_connection_auto_failover(),
10347 12578 lex_mi->m_source_connection_auto_failover);
10348
10349 37734 bool is_or_will_gtid_only_be_enabled = is_option_enabled_or_will_be(
10350 12578 mi->is_gtid_only_mode(), lex_mi->m_gtid_only);
10351 bool will_gtid_only_mode_be_disable =
10352
2/2
✓ Branch 0 taken 3311 times.
✓ Branch 1 taken 9267 times.
15889 mi->is_gtid_only_mode() &&
10353
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 3298 times.
3311 lex_mi->m_gtid_only == LEX_MASTER_INFO::LEX_MI_DISABLE;
10354
10355 auto assign_gtids_to_anonymous_transactions_type =
10356 12578 mi->rli->m_assign_gtids_to_anonymous_transactions_info.get_type();
10357
4/5
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 13 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 12545 times.
✗ Branch 4 not taken.
12578 switch (lex_mi->assign_gtids_to_anonymous_transactions_type) {
10358 11 case LEX_MASTER_INFO::LEX_MI_ANONYMOUS_TO_GTID_OFF:
10359 11 assign_gtids_to_anonymous_transactions_type =
10360 Assign_gtids_to_anonymous_transactions_info::enum_type::AGAT_OFF;
10361 11 break;
10362 13 case LEX_MASTER_INFO::LEX_MI_ANONYMOUS_TO_GTID_LOCAL:
10363 13 assign_gtids_to_anonymous_transactions_type =
10364 Assign_gtids_to_anonymous_transactions_info::enum_type::AGAT_LOCAL;
10365 13 break;
10366 9 case LEX_MASTER_INFO::LEX_MI_ANONYMOUS_TO_GTID_UUID:
10367 9 assign_gtids_to_anonymous_transactions_type =
10368 Assign_gtids_to_anonymous_transactions_info::enum_type::AGAT_UUID;
10369 9 break;
10370 12545 case LEX_MASTER_INFO::LEX_MI_ANONYMOUS_TO_GTID_UNCHANGED:
10371 12545 break;
10372 default:
10373 assert(0);
10374 break;
10375 }
10376
10377 /* Check phase - enabling options */
10378
10379 /*
10380 We cannot specify auto position and set either the coordinates
10381 on source or replica. If we try to do so, an error message is
10382 printed out.
10383 */
10384
4/4
✓ Branch 0 taken 12508 times.
✓ Branch 1 taken 70 times.
✓ Branch 2 taken 12482 times.
✓ Branch 3 taken 26 times.
12578 if (lex_mi->log_file_name != nullptr || lex_mi->pos != 0 ||
10385
4/4
✓ Branch 0 taken 12432 times.
✓ Branch 1 taken 50 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 12428 times.
12482 lex_mi->relay_log_name != nullptr || lex_mi->relay_log_pos != 0) {
10386
4/4
✓ Branch 0 taken 147 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 147 times.
297 if (lex_mi->auto_position == LEX_MASTER_INFO::LEX_MI_ENABLE ||
10387
3/4
✓ Branch 0 taken 133 times.
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 133 times.
280 (lex_mi->auto_position != LEX_MASTER_INFO::LEX_MI_DISABLE &&
10388 133 mi->is_auto_position())) {
10389 3 error = ER_BAD_SLAVE_AUTO_POSITION;
10390 3 my_error(error, MYF(0));
10391 3 return error;
10392 }
10393 }
10394
10395 /*
10396 CHANGE REPLICATION SOURCE TO ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS != OFF
10397 requires
10398 SOURCE_AUTO_POSITION = 0
10399 */
10400
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 12552 times.
12575 if (assign_gtids_to_anonymous_transactions_type !=
10401
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 21 times.
23 Assign_gtids_to_anonymous_transactions_info::enum_type::AGAT_OFF &&
10402 is_or_will_auto_position_be_enabled) {
10403 2 error = ER_CANT_COMBINE_ANONYMOUS_TO_GTID_AND_AUTOPOSITION;
10404 2 my_error(error, MYF(0));
10405 2 return error;
10406 }
10407
10408 /*
10409 CHANGE REPLICATION SOURCE TO GTID_ONLY = 1 requires
10410 SOURCE_AUTO_POSITION = 1
10411 REQUIRE_ROW_FORMAT = 1
10412 */
10413
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 12556 times.
12573 if (lex_mi->m_gtid_only == LEX_MASTER_INFO::LEX_MI_ENABLE &&
10414
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 1 times.
17 (!is_or_will_auto_position_be_enabled ||
10415
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 15 times.
16 !is_or_will_require_row_format_be_enabled)) {
10416 2 error = ER_CHANGE_REPLICATION_SOURCE_NO_OPTIONS_FOR_GTID_ONLY;
10417 2 my_error(error, MYF(0), mi->get_channel());
10418 2 return error;
10419 }
10420
10421 /*
10422 CHANGE REPLICATION SOURCE TO SOURCE_CONNECTION_AUTO_FAILOVER = 1 requires
10423 SOURCE_AUTO_POSITION = 1
10424 */
10425
2/2
✓ Branch 0 taken 87 times.
✓ Branch 1 taken 12484 times.
12571 if (lex_mi->m_source_connection_auto_failover ==
10426 87 LEX_MASTER_INFO::LEX_MI_ENABLE &&
10427
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 81 times.
87 !is_or_will_auto_position_be_enabled) {
10428 6 error = ER_RPL_ASYNC_RECONNECT_AUTO_POSITION_OFF;
10429 6 my_error(error, MYF(0));
10430 6 return error;
10431 }
10432
10433 /*
10434 We need to check if there is an empty master_host. Otherwise
10435 change master succeeds, a master.info file is created containing
10436 empty master_host string and when issuing: start replica; an error
10437 is thrown stating that the server is not configured as replica.
10438 (See BUG#28796).
10439 */
10440
4/4
✓ Branch 0 taken 8556 times.
✓ Branch 1 taken 4009 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 8554 times.
12565 if (lex_mi->host && !*lex_mi->host) {
10441 2 error = ER_WRONG_ARGUMENTS;
10442 2 my_error(error, MYF(0), "MASTER_HOST");
10443 2 return error;
10444 }
10445
10446 /*
10447 Changing source_connection_auto_failover option is not allowed on group
10448 secondary member.
10449 */
10450 25126 if (lex_mi->m_source_connection_auto_failover !=
10451
4/4
✓ Branch 0 taken 99 times.
✓ Branch 1 taken 12464 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 12562 times.
12662 LEX_MASTER_INFO::LEX_MI_UNCHANGED &&
10452
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 98 times.
99 is_group_replication_member_secondary()) {
10453 1 error = ER_OPERATION_NOT_ALLOWED_ON_GR_SECONDARY;
10454 1 my_error(error, MYF(0));
10455 1 return error;
10456 }
10457
10458 /*
10459 CHANGE REPLICATION SOURCE TO ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS != OFF
10460 can't use the same value as the group replication name or view change uuid
10461 */
10462
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 12541 times.
12562 if (lex_mi->assign_gtids_to_anonymous_transactions_type >
10463 LEX_MASTER_INFO::LEX_MI_ANONYMOUS_TO_GTID_OFF) {
10464
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 std::string group_name = get_group_replication_group_name();
10465
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 13 times.
21 if (group_name.length() > 0) {
10466 8 bool is_same = false;
10467 8 auto type = lex_mi->assign_gtids_to_anonymous_transactions_type;
10468
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
8 if (type == LEX_MASTER_INFO::LEX_MI_ANONYMOUS_TO_GTID_LOCAL)
10469
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!(group_name.compare(::server_uuid))) is_same = true;
10470
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
8 if (type == LEX_MASTER_INFO::LEX_MI_ANONYMOUS_TO_GTID_UUID)
10471
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
6 if (!(group_name.compare(
10472 6 lex_mi->assign_gtids_to_anonymous_transactions_manual_uuid)))
10473 2 is_same = true;
10474
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
8 if (is_same) {
10475 2 error = ER_CANT_USE_SAME_UUID_AS_GROUP_NAME;
10476
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_error(error, MYF(0));
10477 3 return error;
10478 }
10479
10480 6 std::string view_change_uuid;
10481
2/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
6 if (get_group_replication_view_change_uuid(view_change_uuid)) {
10482 /* purecov: begin inspected */
10483 error = ER_GRP_RPL_VIEW_CHANGE_UUID_FAIL_GET_VARIABLE;
10484 my_error(error, MYF(0));
10485 return error;
10486 /* purecov: end */
10487 } else {
10488
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
6 if (type == LEX_MASTER_INFO::LEX_MI_ANONYMOUS_TO_GTID_LOCAL)
10489
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!(view_change_uuid.compare(::server_uuid))) is_same = true;
10490
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 if (type == LEX_MASTER_INFO::LEX_MI_ANONYMOUS_TO_GTID_UUID)
10491
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
4 if (!(view_change_uuid.compare(
10492 4 lex_mi->assign_gtids_to_anonymous_transactions_manual_uuid)))
10493 1 is_same = true;
10494
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5 times.
6 if (is_same) {
10495 1 error = ER_CANT_USE_SAME_UUID_AS_VIEW_CHANGE_UUID;
10496
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(error, MYF(0));
10497 1 return error;
10498 }
10499 }
10500
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1 times.
6 }
10501
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 3 times.
21 }
10502
10503 /* Check phase - disabling options */
10504
10505 /*
10506 CHANGE REPLICATION SOURCE TO ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS
10507 auto_position cannot be disable if either source_connection_auto_failover
10508 option is enabled or getting enabled in current CHANGE MASTER statement.
10509 */
10510
4/4
✓ Branch 0 taken 1118 times.
✓ Branch 1 taken 11441 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 1115 times.
12559 if (will_auto_position_be_disable &&
10511 is_or_will_source_connection_auto_failover_be_enabled) {
10512 3 error = ER_DISABLE_AUTO_POSITION_REQUIRES_ASYNC_RECONNECT_OFF;
10513 3 my_error(error, MYF(0));
10514 3 return error;
10515 }
10516
10517 /*
10518 CHANGE REPLICATION SOURCE TO SOURCE_AUTO_POSITION = 0 cannot be done when
10519 GTID_ONLY = 1
10520 */
10521
4/4
✓ Branch 0 taken 1115 times.
✓ Branch 1 taken 11441 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1114 times.
12556 if (will_auto_position_be_disable && is_or_will_gtid_only_be_enabled) {
10522 1 error = ER_CHANGE_REP_SOURCE_CANT_DISABLE_AUTO_POSITION_WITH_GTID_ONLY;
10523 1 my_error(error, MYF(0), mi->get_channel());
10524 1 return error;
10525 }
10526 /*
10527 CHANGE REPLICATION SOURCE TO REQUIRE_ROW_FORMAT = 0 cannot be done when
10528 GTID_ONLY = 1
10529 */
10530
4/4
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 12523 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 31 times.
12555 if (will_require_row_format_be_disable && is_or_will_gtid_only_be_enabled) {
10531 1 error = ER_CHANGE_REP_SOURCE_CANT_DISABLE_REQ_ROW_FORMAT_WITH_GTID_ONLY;
10532 1 my_error(error, MYF(0), mi->get_channel());
10533 1 return error;
10534 }
10535
10536 /*
10537 CHANGE REPLICATION SOURCE TO SOURCE_AUTO_POSITION = 0 when
10538 source positions in relation to the source are invalid.
10539 This requires `SOURCE_LOG_FILE` and `SOURCE_LOG_POS`
10540 The message varies if you are also disabling `GTID_ONLY`
10541 */
10542
2/2
✓ Branch 0 taken 1114 times.
✓ Branch 1 taken 11440 times.
12554 if (will_auto_position_be_disable) {
10543
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1110 times.
1114 if (mi->is_receiver_position_info_invalid()) {
10544
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
4 if (lex_mi->log_file_name == nullptr || lex_mi->pos == 0) {
10545
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (will_gtid_only_mode_be_disable) {
10546 1 error = ER_CHANGE_REP_SOURCE_CANT_DISABLE_GTID_ONLY_WITHOUT_POSITIONS;
10547 1 my_error(error, MYF(0), mi->get_channel());
10548 } else {
10549 1 error = ER_CHANGE_REP_SOURCE_CANT_DISABLE_AUTO_POS_WITHOUT_POSITIONS;
10550 1 my_error(error, MYF(0), mi->get_channel());
10551 }
10552 2 return error;
10553 }
10554 }
10555 }
10556 12552 return error;
10557 }
10558
10559 /**
10560 Log a warning in case GTID_ONLY or SOURCE AUTO POSITION are disabled
10561 and the server contains invalid positions.
10562
10563 @param thd the associated thread object
10564
10565 @param lex_mi structure that holds all change replication source options given
10566 on the command
10567
10568 @param mi Pointer to Master_info object
10569 */
10570 12507 static void log_invalid_position_warning(THD *thd,
10571 const LEX_MASTER_INFO *lex_mi,
10572 Master_info *mi) {
10573
2/2
✓ Branch 0 taken 9723 times.
✓ Branch 1 taken 2784 times.
12507 if (lex_mi->m_gtid_only == LEX_MASTER_INFO::LEX_MI_DISABLE ||
10574
2/2
✓ Branch 0 taken 1143 times.
✓ Branch 1 taken 8580 times.
9723 lex_mi->auto_position == LEX_MASTER_INFO::LEX_MI_DISABLE) {
10575
4/4
✓ Branch 0 taken 3925 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 3924 times.
7852 if (mi->is_receiver_position_info_invalid() ||
10576
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3924 times.
3925 mi->rli->is_applier_source_position_info_invalid()) {
10577 3 push_warning_printf(
10578 thd, Sql_condition::SL_WARNING,
10579 ER_WARN_C_DISABLE_GTID_ONLY_WITH_SOURCE_AUTO_POS_INVALID_POS,
10580 ER_THD(thd,
10581 ER_WARN_C_DISABLE_GTID_ONLY_WITH_SOURCE_AUTO_POS_INVALID_POS),
10582 mi->get_channel());
10583
7/14
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 3 times.
✗ Branch 13 not taken.
3 LogErr(WARNING_LEVEL,
10584 ER_WARN_L_DISABLE_GTID_ONLY_WITH_SOURCE_AUTO_POS_INVALID_POS,
10585 mi->get_channel());
10586 }
10587 }
10588 12507 }
10589
10590 /**
10591 This method aggregates the validation checks made for the command
10592 CHANGE REPLICATION SOURCE
10593
10594 @param thd Pointer to THD object for the client thread executing the
10595 statement.
10596
10597 @param lex_mi structure that holds all change replication source options given
10598 on the command
10599
10600 @param mi Pointer to Master_info object for the channel that holds the
10601 the configuration
10602
10603 @param thread_mask The thread mask identifying which threads are running
10604
10605 @return A pair of booleans <return_value, remove_mta_info>
10606 return_value: true if an error occurred, false otherwise
10607 remove_mta_info: if true remove MTA worker info
10608 */
10609 12549 static std::pair<bool, bool> validate_change_replication_source_options(
10610 THD *thd, const LEX_MASTER_INFO *lex_mi, Master_info *mi, int thread_mask) {
10611 12549 bool mta_remove_worker_info = false;
10612
2/2
✓ Branch 0 taken 12525 times.
✓ Branch 1 taken 24 times.
12549 if ((thread_mask & SLAVE_SQL) == 0) // If execute threads are stopped
10613 {
10614
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 12523 times.
12525 if (mi->rli->mts_recovery_group_cnt) {
10615 /*
10616 Change-Master can't be done if there is a mts group gap.
10617 That requires mts-recovery which START SLAVE provides.
10618 */
10619
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 assert(mi->rli->recovery_parallel_workers);
10620
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_error(ER_MTS_CHANGE_MASTER_CANT_RUN_WITH_GAPS, MYF(0));
10621
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 return std::make_pair(true, mta_remove_worker_info);
10622 } else {
10623 /*
10624 Lack of mts group gaps makes Workers info stale regardless of
10625 need_relay_log_purge computation. We set the mta_remove_worker_info
10626 flag here and call reset_workers() later to delete the worker info
10627 in mysql.slave_worker_info table.
10628 */
10629
2/2
✓ Branch 0 taken 1350 times.
✓ Branch 1 taken 11173 times.
12523 if (mi->rli->recovery_parallel_workers) mta_remove_worker_info = true;
10630 }
10631 }
10632
10633 /*
10634 When give a warning?
10635 CHANGE MASTER command is used in three ways:
10636 a) To change a connection configuration but remain connected to
10637 the same master.
10638 b) To change positions in binary or relay log(eg: master_log_pos).
10639 c) To change the master you are replicating from.
10640 We give a warning in cases b and c.
10641 */
10642
6/6
✓ Branch 0 taken 3968 times.
✓ Branch 1 taken 32 times.
✓ Branch 2 taken 3940 times.
✓ Branch 3 taken 28 times.
✓ Branch 4 taken 3921 times.
✓ Branch 5 taken 19 times.
4000 if ((lex_mi->host || lex_mi->port || lex_mi->log_file_name || lex_mi->pos ||
10643
10/10
✓ Branch 0 taken 4000 times.
✓ Branch 1 taken 8547 times.
✓ Branch 2 taken 3883 times.
✓ Branch 3 taken 38 times.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 3879 times.
✓ Branch 6 taken 5 times.
✓ Branch 7 taken 8663 times.
✓ Branch 8 taken 5 times.
✓ Branch 9 taken 12542 times.
25136 lex_mi->relay_log_name || lex_mi->relay_log_pos) &&
10644 8668 (mi->rli->atomic_channel_open_temp_tables > 0))
10645
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
5 push_warning(thd, Sql_condition::SL_WARNING,
10646 ER_WARN_OPEN_TEMP_TABLES_MUST_BE_ZERO,
10647 ER_THD(thd, ER_WARN_OPEN_TEMP_TABLES_MUST_BE_ZERO));
10648
10649 /**
10650 Although this check is redone when the user is set, we do an early
10651 check here to avoid failures in the middle of configuration
10652 */
10653 Relay_log_info::enum_priv_checks_status priv_check_error;
10654 12547 priv_check_error = mi->rli->check_privilege_checks_user(
10655
1/2
✓ Branch 0 taken 12547 times.
✗ Branch 1 not taken.
12547 lex_mi->privilege_checks_username,
10656
2/2
✓ Branch 0 taken 2797 times.
✓ Branch 1 taken 9750 times.
12547 lex_mi->privilege_checks_none ? nullptr
10657 : lex_mi->privilege_checks_hostname);
10658
2/4
✓ Branch 0 taken 12547 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12547 times.
12547 if (!!priv_check_error) {
10659 mi->rli->report_privilege_check_error(
10660 ERROR_LEVEL, priv_check_error, true /* to client*/,
10661 mi->rli->get_channel(), lex_mi->privilege_checks_username,
10662 lex_mi->privilege_checks_hostname);
10663 return std::make_pair(true, mta_remove_worker_info);
10664 }
10665
1/2
✓ Branch 0 taken 12547 times.
✗ Branch 1 not taken.
12547 return std::make_pair(false, mta_remove_worker_info);
10666 }
10667
10668 /**
10669 This method aggregates the the instantiation of options for the command
10670 CHANGE REPLICATION SOURCE
10671
10672 @param thd Pointer to THD object for the client thread executing the
10673 statement.
10674
10675 @param lex_mi structure that holds all change replication source options given
10676 on the command
10677
10678 @param mi Pointer to Master_info object belonging to the replica channel
10679 to be configured
10680
10681 @param have_both_receive_execute_option the command will change options that
10682 affect both the applier and receiver
10683
10684 @param have_execute_option the command will change applier related options
10685
10686 @param have_receive_option the command will change receiver related options
10687
10688 @return returns true if an error occurred, false otherwise
10689 */
10690 12547 static bool update_change_replication_source_options(
10691 THD *thd, LEX_MASTER_INFO *lex_mi, Master_info *mi,
10692 bool have_both_receive_execute_option, bool have_execute_option,
10693 bool have_receive_option) {
10694
2/2
✓ Branch 0 taken 5781 times.
✓ Branch 1 taken 6766 times.
12547 if (have_both_receive_execute_option) {
10695
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5781 times.
5781 if (change_applier_receiver_options(thd, lex_mi, mi)) {
10696 return true;
10697 }
10698 }
10699
10700
2/2
✓ Branch 0 taken 6706 times.
✓ Branch 1 taken 5841 times.
12547 if (channel_map.is_group_replication_channel_name(lex_mi->channel)) {
10701 6706 mi->set_auto_position(true);
10702 6706 mi->rli->set_require_row_format(true);
10703 6706 mi->set_gtid_only_mode(true);
10704 }
10705
10706
4/6
✓ Branch 0 taken 3051 times.
✓ Branch 1 taken 9496 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3051 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 12547 times.
12547 if (have_execute_option && change_execute_options(lex_mi, mi)) return true;
10707
10708
2/2
✓ Branch 0 taken 11130 times.
✓ Branch 1 taken 1417 times.
12547 if (have_receive_option) {
10709
2/2
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 11093 times.
11130 if (change_receive_options(thd, lex_mi, mi)) {
10710 37 return true;
10711 }
10712 }
10713
10714 12510 return false;
10715 }
10716
10717 /**
10718 Execute a CHANGE MASTER statement.
10719
10720 Apart from changing the receive/execute configurations/positions,
10721 this function also does the following:
10722 - May leave replicated open temporary table after warning.
10723 - Purges relay logs if no threads running and no relay log file/pos options.
10724 - Delete worker info in mysql.slave_worker_info table if applier not running.
10725
10726 @param thd Pointer to THD object for the client thread executing
10727 the statement.
10728
10729 @param mi Pointer to Master_info object belonging to the slave's
10730 IO thread.
10731
10732 @param lex_mi Lex information with master connection data.
10733 Coming from the an executing statement or set directly
10734 this shall contain connection settings like hostname,
10735 user, password and other settings like the number of
10736 connection retries.
10737
10738 @param preserve_logs If the decision of purging the logs should be always be
10739 false even if no relay log name/position is given to
10740 the method. The preserve_logs parameter will not be
10741 respected when the relay log info repository is not
10742 initialized.
10743
10744 @retval 0 success
10745 @retval !=0 error
10746 */
10747 12652 int change_master(THD *thd, Master_info *mi, LEX_MASTER_INFO *lex_mi,
10748 bool preserve_logs) {
10749 12652 int error = 0;
10750
10751 /* Do we have at least one receive related (IO thread) option? */
10752 12652 bool have_receive_option = false;
10753 /* Do we have at least one execute related (SQL/coord/worker) option? */
10754 12652 bool have_execute_option = false;
10755 /* Do we have at least one option that relates to receival and execution? */
10756 12652 bool have_both_receive_execute_option = false;
10757 /** Is there a an error during validation */
10758 12652 bool validation_error = false;
10759 /* If there are no mts gaps, we delete the rows in this table. */
10760 12652 bool mta_remove_worker_info = false;
10761 /* used as a bit mask to indicate running slave threads. */
10762 int thread_mask;
10763 /*
10764 Relay logs are purged only if both receive and execute threads are
10765 stopped before executing CHANGE MASTER and relay_log_file/relay_log_pos
10766 options are not used.
10767 */
10768 12652 bool need_relay_log_purge = true;
10769
10770 /*
10771 We want to save the old receive configurations so that we can use them to
10772 print the changes in these configurations (from-to form). This is used in
10773 LogErr() later.
10774 */
10775 char saved_host[HOSTNAME_LENGTH + 1], saved_bind_addr[HOSTNAME_LENGTH + 1];
10776 12652 uint saved_port = 0;
10777 char saved_log_name[FN_REFLEN];
10778 12652 my_off_t saved_log_pos = 0;
10779
10780
1/2
✓ Branch 0 taken 12652 times.
✗ Branch 1 not taken.
12652 DBUG_TRACE;
10781
10782 /*
10783 CHANGE MASTER command should ignore 'read-only' and 'super_read_only'
10784 options so that it can update 'mysql.slave_master_info' replication
10785 repository tables.
10786 */
10787 12652 thd->set_skip_readonly_check();
10788
1/2
✓ Branch 0 taken 12652 times.
✗ Branch 1 not taken.
12652 mi->channel_wrlock();
10789 /*
10790 When we change master, we first decide which thread is running and
10791 which is not. We dont want this assumption to break while we change master.
10792
10793 Suppose we decide that receiver thread is running and thus it is
10794 safe to change receive related options in mi. By this time if
10795 the receive thread is started, we may have a race condition between
10796 the client thread and receiver thread.
10797 */
10798
1/2
✓ Branch 0 taken 12652 times.
✗ Branch 1 not taken.
12652 lock_slave_threads(mi);
10799
10800 /*
10801 Get a bit mask for the slave threads that are running.
10802 Since the third argument is 0, thread_mask after the function
10803 returns stands for running threads.
10804 */
10805
1/2
✓ Branch 0 taken 12652 times.
✗ Branch 1 not taken.
12652 init_thread_mask(&thread_mask, mi, false);
10806
10807
2/2
✓ Branch 0 taken 112 times.
✓ Branch 1 taken 12540 times.
12652 if (thread_mask) /* If any thread is running */
10808 {
10809 /*
10810 Prior to WL#6120, we imposed the condition that STOP SLAVE is required
10811 before CHANGE MASTER. Since the slave threads die on STOP SLAVE, it was
10812 fine if we purged relay logs.
10813
10814 Now that we do allow CHANGE MASTER with a running receiver/applier thread,
10815 we need to make sure that the relay logs are purged only if both
10816 receiver and applier threads are stopped otherwise we could lose events.
10817
10818 The idea behind purging relay logs if both the threads are stopped is to
10819 keep consistency with the old behavior. If the user/application is doing
10820 a CHANGE MASTER without stopping any one thread, the relay log purge
10821 should be controlled via the 'relay_log_purge' option.
10822 */
10823 112 need_relay_log_purge = false;
10824 }
10825
10826 /* Check if at least one receive option is given on change master */
10827
1/2
✓ Branch 0 taken 12652 times.
✗ Branch 1 not taken.
12652 have_receive_option = have_change_replication_source_receive_option(lex_mi);
10828
10829 /* Check if at least one execute option is given on change master */
10830
1/2
✓ Branch 0 taken 12652 times.
✗ Branch 1 not taken.
12652 have_execute_option = have_change_replication_source_execute_option(
10831 lex_mi, &need_relay_log_purge);
10832 /* Check if at least one execute option affects both the applier and receiver
10833 */
10834 have_both_receive_execute_option =
10835
1/2
✓ Branch 0 taken 12652 times.
✗ Branch 1 not taken.
12652 have_change_replication_source_applier_and_receive_option(lex_mi);
10836
10837 /* If either:
10838 + An option affects both the applier and receiver and one of the threads
10839 is running
10840 + There are receiver and applier options and both threads are running
10841 Then tell the user the replica must stop
10842 */
10843
2/2
✓ Branch 0 taken 5831 times.
✓ Branch 1 taken 6821 times.
12652 if ((have_both_receive_execute_option &&
10844
6/6
✓ Branch 0 taken 5825 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 5822 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 11184 times.
✓ Branch 5 taken 1459 times.
12652 ((thread_mask & SLAVE_IO) || (thread_mask & SLAVE_SQL))) ||
10845
4/4
✓ Branch 0 taken 2905 times.
✓ Branch 1 taken 8279 times.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 2885 times.
11184 (have_receive_option && have_execute_option && (thread_mask & SLAVE_IO) &&
10846
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 17 times.
20 (thread_mask & SLAVE_SQL))) {
10847 12 error = ER_SLAVE_CHANNEL_MUST_STOP;
10848
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 my_error(ER_SLAVE_CHANNEL_MUST_STOP, MYF(0), mi->get_channel());
10849 12 goto err;
10850 }
10851
10852 /* With receiver thread running, we dont allow changing receive options. */
10853
4/4
✓ Branch 0 taken 11181 times.
✓ Branch 1 taken 1459 times.
✓ Branch 2 taken 31 times.
✓ Branch 3 taken 11150 times.
12640 if (have_receive_option && (thread_mask & SLAVE_IO)) {
10854 31 error = ER_SLAVE_CHANNEL_IO_THREAD_MUST_STOP;
10855
1/2
✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
31 my_error(ER_SLAVE_CHANNEL_IO_THREAD_MUST_STOP, MYF(0), mi->get_channel());
10856 31 goto err;
10857 }
10858
10859 /* With an execute thread running, we don't allow changing execute options. */
10860
4/4
✓ Branch 0 taken 3068 times.
✓ Branch 1 taken 9541 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 3056 times.
12609 if (have_execute_option && (thread_mask & SLAVE_SQL)) {
10861 12 error = ER_SLAVE_CHANNEL_SQL_THREAD_MUST_STOP;
10862
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 my_error(ER_SLAVE_CHANNEL_SQL_THREAD_MUST_STOP, MYF(0), mi->get_channel());
10863 12 goto err;
10864 }
10865
10866 /* If GTID_MODE is different from ON check if some options are invalid
10867 We hold channel_map lock for the duration of the CHANGE MASTER.
10868 This is important since it prevents that a concurrent
10869 connection changes to GTID_MODE=OFF between this check and the
10870 point where AUTO_POSITION is stored in the table and in mi.
10871 */
10872
3/4
✓ Branch 0 taken 12597 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3248 times.
✓ Branch 3 taken 9349 times.
12597 if (global_gtid_mode.get() != Gtid_mode::ON) {
10873
3/4
✓ Branch 0 taken 3248 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19 times.
✓ Branch 3 taken 3229 times.
3248 if ((error = validate_gtid_option_restrictions(lex_mi, mi))) {
10874 19 goto err;
10875 }
10876 }
10877
10878
3/4
✓ Branch 0 taken 12578 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 26 times.
✓ Branch 3 taken 12552 times.
12578 if ((error = evaluate_inter_option_dependencies(lex_mi, mi))) {
10879 26 goto err;
10880 }
10881
10882
4/4
✓ Branch 0 taken 12442 times.
✓ Branch 1 taken 110 times.
✓ Branch 2 taken 2264 times.
✓ Branch 3 taken 10178 times.
12552 if (need_relay_log_purge && /* If we should purge the logs for this channel */
10883 2264 preserve_logs && /* And we were asked to keep them */
10884
2/2
✓ Branch 0 taken 591 times.
✓ Branch 1 taken 1673 times.
2264 mi->rli->inited) /* And the channel was initialized properly */
10885 {
10886 591 need_relay_log_purge = false;
10887 }
10888
10889
1/2
✓ Branch 0 taken 12552 times.
✗ Branch 1 not taken.
12552 THD_STAGE_INFO(thd, stage_changing_source);
10890
10891 int thread_mask_stopped_threads;
10892
10893 /*
10894 Before load_mi_and_rli_from_repositories() call, get a bit mask to indicate
10895 stopped threads in thread_mask_stopped_threads. Since the third argguement
10896 is 1, thread_mask when the function returns stands for stopped threads.
10897 */
10898
10899
1/2
✓ Branch 0 taken 12552 times.
✗ Branch 1 not taken.
12552 init_thread_mask(&thread_mask_stopped_threads, mi, true);
10900
10901
3/4
✓ Branch 0 taken 12552 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 12549 times.
12552 if (load_mi_and_rli_from_repositories(mi, false, thread_mask_stopped_threads,
10902 need_relay_log_purge)) {
10903 3 error = ER_MASTER_INFO;
10904
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 my_error(ER_MASTER_INFO, MYF(0));
10905 3 goto err;
10906 }
10907
10908 12549 std::tie(validation_error, mta_remove_worker_info) =
10909
1/2
✓ Branch 0 taken 12549 times.
✗ Branch 1 not taken.
25098 validate_change_replication_source_options(thd, lex_mi, mi, thread_mask);
10910
10911
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 12547 times.
12549 if (validation_error) {
10912 2 error = 1;
10913 2 goto err;
10914 }
10915
10916 /*
10917 Validation operations should be above this comment
10918 Try to use the validate_change_replication_source_options method
10919
10920 Changes to variables should be below this comment
10921 Try to use the update_change_replication_source_options method
10922 */
10923
10924
2/2
✓ Branch 0 taken 11130 times.
✓ Branch 1 taken 1417 times.
12547 if (have_receive_option) {
10925
1/2
✓ Branch 0 taken 11130 times.
✗ Branch 1 not taken.
11130 strmake(saved_host, mi->host, HOSTNAME_LENGTH);
10926
1/2
✓ Branch 0 taken 11130 times.
✗ Branch 1 not taken.
11130 strmake(saved_bind_addr, mi->bind_addr, HOSTNAME_LENGTH);
10927 11130 saved_port = mi->port;
10928
1/2
✓ Branch 0 taken 11130 times.
✗ Branch 1 not taken.
11130 strmake(saved_log_name, mi->get_master_log_name(), FN_REFLEN - 1);
10929 11130 saved_log_pos = mi->get_master_log_pos();
10930 }
10931
10932
3/4
✓ Branch 0 taken 12547 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 37 times.
✓ Branch 3 taken 12510 times.
12547 if (update_change_replication_source_options(
10933 thd, lex_mi, mi, have_both_receive_execute_option,
10934 have_execute_option, have_receive_option)) {
10935 37 error = 1;
10936 37 goto err;
10937 }
10938
10939 /*
10940 If user didn't specify neither host nor port nor any log name nor any log
10941 pos, i.e. he specified only user/password/master_connect_retry,
10942 master_delay, he probably wants replication to resume from where it had
10943 left, i.e. from the coordinates of the **SQL** thread (imagine the case
10944 where the I/O is ahead of the SQL; restarting from the coordinates of the
10945 I/O would lose some events which is probably unwanted when you are just
10946 doing minor changes like changing master_connect_retry). Note: coordinates
10947 of the SQL thread must be read before the block which resets them.
10948 */
10949
2/2
✓ Branch 0 taken 11810 times.
✓ Branch 1 taken 700 times.
12510 if (need_relay_log_purge) {
10950 /*
10951 A side-effect is that if only the I/O thread was started, this thread may
10952 restart from ''/4 after the CHANGE MASTER. That's a minor problem (it is a
10953 much more unlikely situation than the one we are fixing here).
10954 */
10955
4/4
✓ Branch 0 taken 3876 times.
✓ Branch 1 taken 32 times.
✓ Branch 2 taken 3854 times.
✓ Branch 3 taken 22 times.
3908 if (!lex_mi->host && !lex_mi->port && !lex_mi->log_file_name &&
10956
9/10
✓ Branch 0 taken 3908 times.
✓ Branch 1 taken 7902 times.
✓ Branch 2 taken 3835 times.
✓ Branch 3 taken 19 times.
✓ Branch 4 taken 3835 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3826 times.
✓ Branch 7 taken 9 times.
✓ Branch 8 taken 3826 times.
✓ Branch 9 taken 7984 times.
15718 !lex_mi->pos && !mi->rli->is_applier_source_position_info_invalid()) {
10957 /*
10958 Sometimes mi->rli->master_log_pos == 0 (it happens when the SQL thread
10959 is not initialized), so we use a max(). What happens to
10960 mi->rli->master_log_pos during the initialization stages of replication
10961 is not 100% clear, so we guard against problems using max().
10962 */
10963 3826 mi->set_master_log_pos(max<ulonglong>(
10964 3826 BIN_LOG_HEADER_SIZE, mi->rli->get_group_master_log_pos()));
10965
1/2
✓ Branch 0 taken 3826 times.
✗ Branch 1 not taken.
3826 mi->set_master_log_name(mi->rli->get_group_master_log_name());
10966 }
10967 }
10968
10969
2/2
✓ Branch 0 taken 11093 times.
✓ Branch 1 taken 1417 times.
12510 if (have_receive_option)
10970
9/18
✓ Branch 0 taken 11093 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11093 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11093 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 11093 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 11093 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 11093 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 11093 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 11093 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 11093 times.
✗ Branch 17 not taken.
11093 LogErr(SYSTEM_LEVEL, ER_SLAVE_CHANGE_MASTER_TO_EXECUTED,
10971 mi->get_for_channel_str(true), saved_host, saved_port,
10972 saved_log_name, (ulong)saved_log_pos, saved_bind_addr, mi->host,
10973 mi->port, mi->get_master_log_name(), (ulong)mi->get_master_log_pos(),
10974 mi->bind_addr);
10975
10976 /* If the receiver is stopped, flush master_info to disk. */
10977
5/8
✓ Branch 0 taken 12477 times.
✓ Branch 1 taken 33 times.
✓ Branch 2 taken 12477 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 12477 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 12510 times.
12510 if ((thread_mask & SLAVE_IO) == 0 && flush_master_info(mi, true)) {
10978 error = ER_RELAY_LOG_INIT;
10979 my_error(ER_RELAY_LOG_INIT, MYF(0), "Failed to flush master info file");
10980 goto err;
10981 }
10982
10983
2/2
✓ Branch 0 taken 12486 times.
✓ Branch 1 taken 24 times.
12510 if ((thread_mask & SLAVE_SQL) == 0) /* Applier module is not executing */
10984 {
10985
2/2
✓ Branch 0 taken 11810 times.
✓ Branch 1 taken 676 times.
12486 if (need_relay_log_purge) {
10986 /*
10987 'if (need_relay_log_purge)' implicitly means that all slave threads are
10988 stopped and there is no use of relay_log_file/relay_log_pos options.
10989 We need not check these here again.
10990 */
10991
10992 /* purge_relay_log() returns pointer to an error message here. */
10993 11810 const char *errmsg = nullptr;
10994 /*
10995 purge_relay_log() assumes that we have run_lock and no slave threads
10996 are running.
10997 */
10998
1/2
✓ Branch 0 taken 11810 times.
✗ Branch 1 not taken.
11810 THD_STAGE_INFO(thd, stage_purging_old_relay_logs);
10999
3/4
✓ Branch 0 taken 11810 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 11807 times.
11810 if (mi->rli->purge_relay_logs(thd, &errmsg)) {
11000 3 error = ER_RELAY_LOG_FAIL;
11001
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 my_error(ER_RELAY_LOG_FAIL, MYF(0), errmsg);
11002 3 goto err;
11003 }
11004
11005 /*
11006 Coordinates in rli were spoilt by purge_relay_logs(),
11007 so restore them to good values. If we left them to ''/0, that would
11008 work. But that would fail in the case of 2 successive CHANGE MASTER
11009 (without a START SLAVE in between): because first one would set the
11010 coords in mi to the good values of those in rli, then set those i>n rli
11011 to ''/0, then second CHANGE MASTER would set the coords in mi to those
11012 of rli, i.e. to ''/0: we have lost all copies of the original good
11013 coordinates. That's why we always save good coords in rli.
11014 */
11015
3/4
✓ Branch 0 taken 11807 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11800 times.
✓ Branch 3 taken 7 times.
11807 if (!mi->is_receiver_position_info_invalid()) {
11016 11800 mi->rli->set_group_master_log_pos(mi->get_master_log_pos());
11017
1/2
✓ Branch 0 taken 11800 times.
✗ Branch 1 not taken.
11800 mi->rli->set_group_master_log_name(mi->get_master_log_name());
11018
3/8
✓ Branch 0 taken 11800 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11800 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 11800 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
11800 DBUG_PRINT("info", ("master_log_pos: %llu", mi->get_master_log_pos()));
11019 }
11020 } else {
11021 676 const char *errmsg = nullptr;
11022
2/4
✓ Branch 0 taken 676 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 676 times.
676 if (mi->rli->is_group_relay_log_name_invalid(&errmsg)) {
11023 error = ER_RELAY_LOG_INIT;
11024 my_error(ER_RELAY_LOG_INIT, MYF(0), errmsg);
11025 goto err;
11026 }
11027 }
11028
11029 char *var_group_master_log_name =
11030 12483 const_cast<char *>(mi->rli->get_group_master_log_name());
11031
11032
4/4
✓ Branch 0 taken 11517 times.
✓ Branch 1 taken 966 times.
✓ Branch 2 taken 11398 times.
✓ Branch 3 taken 1085 times.
24000 if (!var_group_master_log_name[0] && // uninitialized case
11033
3/4
✓ Branch 0 taken 11517 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11398 times.
✓ Branch 3 taken 119 times.
11517 !mi->rli->is_applier_source_position_info_invalid())
11034 11398 mi->rli->set_group_master_log_pos(0);
11035
11036 12483 mi->rli->abort_pos_wait++; /* for SOURCE_POS_WAIT() to abort */
11037
11038 /* Clear the errors, for a clean start */
11039
1/2
✓ Branch 0 taken 12483 times.
✗ Branch 1 not taken.
12483 mi->rli->clear_error();
11040
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12483 times.
12483 if (mi->rli->workers_array_initialized) {
11041 for (size_t i = 0; i < mi->rli->get_worker_count(); i++) {
11042 mi->rli->get_worker(i)->clear_error();
11043 }
11044 }
11045
11046 /*
11047 If we don't write new coordinates to disk now, then old will remain in
11048 relay-log.info until START SLAVE is issued; but if mysqld is shutdown
11049 before START SLAVE, then old will remain in relay-log.info, and will be
11050 the in-memory value at restart (thus causing errors, as the old relay log
11051 does not exist anymore).
11052
11053 Notice that the rli table is available exclusively as slave is not
11054 running.
11055 */
11056
2/4
✓ Branch 0 taken 12483 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12483 times.
12483 if (mi->rli->flush_info(Relay_log_info::RLI_FLUSH_IGNORE_SYNC_OPT |
11057 Relay_log_info::RLI_FLUSH_IGNORE_GTID_ONLY)) {
11058 error = ER_RELAY_LOG_INIT;
11059 my_error(ER_RELAY_LOG_INIT, MYF(0), "Failed to flush relay info file.");
11060 goto err;
11061 }
11062
11063 } /* end 'if (thread_mask & SLAVE_SQL == 0)' */
11064
11065
1/2
✓ Branch 0 taken 12507 times.
✗ Branch 1 not taken.
12507 log_invalid_position_warning(thd, lex_mi, mi);
11066
11067
2/2
✓ Branch 0 taken 11158 times.
✓ Branch 1 taken 1349 times.
12507 if (mta_remove_worker_info)
11068
3/4
✓ Branch 0 taken 1349 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1348 times.
1349 if (Rpl_info_factory::reset_workers(mi->rli)) {
11069 1 error = ER_MTS_RESET_WORKERS;
11070
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_MTS_RESET_WORKERS, MYF(0));
11071 1 goto err;
11072 }
11073 11158 err:
11074
11075
1/2
✓ Branch 0 taken 12652 times.
✗ Branch 1 not taken.
12652 unlock_slave_threads(mi);
11076
1/2
✓ Branch 0 taken 12652 times.
✗ Branch 1 not taken.
12652 mi->channel_unlock();
11077 12652 return error;
11078 12652 }
11079
11080 /**
11081 This function is first called when the Master_info object
11082 corresponding to a channel in a multisourced slave does not
11083 exist. But before a new channel is created, certain
11084 conditions have to be met. The below function apriorily
11085 checks if all such conditions are met. If all the
11086 conditions are met then it creates a channel i.e
11087 mi<->rli
11088
11089 @param[in,out] mi When new {mi,rli} are created,
11090 the reference is stored in *mi
11091 @param[in] channel The channel on which the change
11092 master was introduced.
11093 */
11094 3823 int add_new_channel(Master_info **mi, const char *channel) {
11095
1/2
✓ Branch 0 taken 3823 times.
✗ Branch 1 not taken.
3823 DBUG_TRACE;
11096
11097 3823 int error = 0;
11098 Ident_name_check ident_check_status;
11099
11100 /*
11101 Refuse to create a new channel if the repositories does not support this.
11102 */
11103
11104
2/2
✓ Branch 0 taken 3821 times.
✓ Branch 1 taken 2 times.
3823 if (opt_mi_repository_id == INFO_REPOSITORY_FILE ||
11105
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3820 times.
3821 opt_rli_repository_id == INFO_REPOSITORY_FILE) {
11106
8/16
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 3 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 3 times.
✗ Branch 15 not taken.
3 LogErr(ERROR_LEVEL,
11107 ER_RPL_SLAVE_NEW_MASTER_INFO_NEEDS_REPOS_TYPE_OTHER_THAN_FILE);
11108 3 error = ER_SLAVE_NEW_CHANNEL_WRONG_REPOSITORY;
11109
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 my_error(ER_SLAVE_NEW_CHANNEL_WRONG_REPOSITORY, MYF(0));
11110 3 goto err;
11111 }
11112
11113 /*
11114 Return if max num of replication channels exceeded already.
11115 */
11116
11117
3/4
✓ Branch 0 taken 3820 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 3819 times.
3820 if (!channel_map.is_valid_channel_count()) {
11118 1 error = ER_SLAVE_MAX_CHANNELS_EXCEEDED;
11119
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_SLAVE_MAX_CHANNELS_EXCEEDED, MYF(0));
11120 1 goto err;
11121 }
11122
11123 /*
11124 Now check the sanity of the channel name. It's length etc. The channel
11125 identifier is similar to table names. So, use check_table_function.
11126 */
11127
1/2
✓ Branch 0 taken 3819 times.
✗ Branch 1 not taken.
3819 if (channel) {
11128
1/2
✓ Branch 0 taken 3819 times.
✗ Branch 1 not taken.
3819 ident_check_status = check_table_name(channel, strlen(channel));
11129 } else
11130 ident_check_status = Ident_name_check::WRONG;
11131
11132
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3816 times.
3819 if (ident_check_status != Ident_name_check::OK) {
11133 3 error = ER_SLAVE_CHANNEL_NAME_INVALID_OR_TOO_LONG;
11134
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 my_error(ER_SLAVE_CHANNEL_NAME_INVALID_OR_TOO_LONG, MYF(0));
11135 3 goto err;
11136 }
11137
11138
3/4
✓ Branch 0 taken 3816 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3815 times.
✓ Branch 3 taken 1 times.
3816 if (!((*mi) = Rpl_info_factory::create_mi_and_rli_objects(
11139 opt_mi_repository_id, opt_rli_repository_id, channel, false,
11140 &channel_map))) {
11141 1 error = ER_MASTER_INFO;
11142
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_MASTER_INFO, MYF(0));
11143 1 goto err;
11144 }
11145
11146 3815 err:
11147
11148 3823 return error;
11149 3823 }
11150
11151 /**
11152 Method used to check if the user is trying to update any other option for
11153 the change master apart from the MASTER_USER and MASTER_PASSWORD.
11154 In case user tries to update any other parameter apart from these two,
11155 this method will return error.
11156
11157 @param lex_mi structure that holds all change master options given on
11158 the change master command.
11159
11160 @retval true - The CHANGE MASTER is updating a unsupported parameter for the
11161 recovery channel.
11162
11163 @retval false - Everything is fine. The CHANGE MASTER can execute with the
11164 given option(s) for the recovery channel.
11165 */
11166 1882 static bool is_invalid_change_master_for_group_replication_recovery(
11167 const LEX_MASTER_INFO *lex_mi) {
11168
1/2
✓ Branch 0 taken 1882 times.
✗ Branch 1 not taken.
1882 DBUG_TRACE;
11169 1882 bool have_extra_option_received = false;
11170
11171 /* Check if *at least one* receive/execute option is given on change master
11172 * command*/
11173
4/6
✓ Branch 0 taken 1880 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1880 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1880 times.
✗ Branch 5 not taken.
1882 if (lex_mi->host || lex_mi->log_file_name || lex_mi->pos ||
11174
4/6
✓ Branch 0 taken 1880 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1879 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1879 times.
✗ Branch 5 not taken.
1880 lex_mi->bind_addr || lex_mi->port || lex_mi->connect_retry ||
11175
1/2
✓ Branch 0 taken 1879 times.
✗ Branch 1 not taken.
1879 lex_mi->server_id ||
11176
2/2
✓ Branch 0 taken 1877 times.
✓ Branch 1 taken 2 times.
1879 lex_mi->auto_position != LEX_MASTER_INFO::LEX_MI_UNCHANGED ||
11177
1/2
✓ Branch 0 taken 1877 times.
✗ Branch 1 not taken.
1877 lex_mi->ssl != LEX_MASTER_INFO::LEX_MI_UNCHANGED ||
11178
1/2
✓ Branch 0 taken 1877 times.
✗ Branch 1 not taken.
1877 lex_mi->ssl_verify_server_cert != LEX_MASTER_INFO::LEX_MI_UNCHANGED ||
11179
1/2
✓ Branch 0 taken 1877 times.
✗ Branch 1 not taken.
1877 lex_mi->heartbeat_opt != LEX_MASTER_INFO::LEX_MI_UNCHANGED ||
11180
1/2
✓ Branch 0 taken 1877 times.
✗ Branch 1 not taken.
1877 lex_mi->retry_count_opt != LEX_MASTER_INFO::LEX_MI_UNCHANGED ||
11181
3/6
✓ Branch 0 taken 1877 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1877 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1877 times.
✗ Branch 5 not taken.
1877 lex_mi->ssl_key || lex_mi->ssl_cert || lex_mi->ssl_ca ||
11182
2/4
✓ Branch 0 taken 1877 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1877 times.
✗ Branch 3 not taken.
1877 lex_mi->ssl_capath || lex_mi->tls_version ||
11183
2/2
✓ Branch 0 taken 1876 times.
✓ Branch 1 taken 1 times.
1877 lex_mi->tls_ciphersuites != LEX_MASTER_INFO::UNSPECIFIED ||
11184
3/6
✓ Branch 0 taken 1876 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1876 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1876 times.
✗ Branch 5 not taken.
1876 lex_mi->ssl_cipher || lex_mi->ssl_crl || lex_mi->ssl_crlpath ||
11185
1/2
✓ Branch 0 taken 1876 times.
✗ Branch 1 not taken.
1876 lex_mi->repl_ignore_server_ids_opt == LEX_MASTER_INFO::LEX_MI_ENABLE ||
11186
2/4
✓ Branch 0 taken 1876 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1876 times.
✗ Branch 3 not taken.
1876 lex_mi->relay_log_name || lex_mi->relay_log_pos ||
11187
2/4
✓ Branch 0 taken 1876 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1876 times.
✗ Branch 3 not taken.
1876 lex_mi->sql_delay != -1 || lex_mi->public_key_path ||
11188
1/2
✓ Branch 0 taken 1876 times.
✗ Branch 1 not taken.
1876 lex_mi->get_public_key != LEX_MASTER_INFO::LEX_MI_UNCHANGED ||
11189
2/4
✓ Branch 0 taken 1876 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1876 times.
✗ Branch 3 not taken.
1876 lex_mi->zstd_compression_level || lex_mi->compression_algorithm ||
11190
2/2
✓ Branch 0 taken 1874 times.
✓ Branch 1 taken 2 times.
1876 lex_mi->require_row_format != LEX_MASTER_INFO::LEX_MI_UNCHANGED ||
11191
2/2
✓ Branch 0 taken 1873 times.
✓ Branch 1 taken 1 times.
1874 lex_mi->m_source_connection_auto_failover !=
11192 1873 LEX_MASTER_INFO::LEX_MI_UNCHANGED ||
11193
1/2
✓ Branch 0 taken 1873 times.
✗ Branch 1 not taken.
1873 lex_mi->assign_gtids_to_anonymous_transactions_type !=
11194 1873 LEX_MASTER_INFO::LEX_MI_ANONYMOUS_TO_GTID_UNCHANGED ||
11195
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1871 times.
1873 lex_mi->m_gtid_only != LEX_MASTER_INFO::LEX_MI_UNCHANGED)
11196 11 have_extra_option_received = true;
11197
11198 1882 return have_extra_option_received;
11199 1882 }
11200
11201 /**
11202 Method used to check if the user is trying to update any other option for
11203 the change master apart from the PRIVILEGE_CHECKS_USER.
11204 In case user tries to update any other parameter apart from this one, this
11205 method will return error.
11206
11207 @param lex_mi structure that holds all change master options given on
11208 the change master command.
11209
11210 @retval true - The CHANGE MASTER is updating a unsupported parameter for the
11211 recovery channel.
11212
11213 @retval false - Everything is fine. The CHANGE MASTER can execute with the
11214 given option(s) for the recovery channel.
11215 */
11216 20 static bool is_invalid_change_master_for_group_replication_applier(
11217 const LEX_MASTER_INFO *lex_mi) {
11218
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 DBUG_TRACE;
11219 20 bool have_extra_option_received = false;
11220
11221 /* Check if *at least one* receive/execute option is given on change master
11222 * command*/
11223
4/6
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 17 times.
✗ Branch 5 not taken.
20 if (lex_mi->host || lex_mi->user || lex_mi->password ||
11224
3/6
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 17 times.
✗ Branch 5 not taken.
17 lex_mi->log_file_name || lex_mi->pos || lex_mi->bind_addr ||
11225
3/6
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 17 times.
✗ Branch 5 not taken.
17 lex_mi->port || lex_mi->connect_retry || lex_mi->server_id ||
11226
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 2 times.
17 lex_mi->auto_position != LEX_MASTER_INFO::LEX_MI_UNCHANGED ||
11227
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 lex_mi->ssl != LEX_MASTER_INFO::LEX_MI_UNCHANGED ||
11228
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 lex_mi->ssl_verify_server_cert != LEX_MASTER_INFO::LEX_MI_UNCHANGED ||
11229
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 lex_mi->heartbeat_opt != LEX_MASTER_INFO::LEX_MI_UNCHANGED ||
11230
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 lex_mi->retry_count_opt != LEX_MASTER_INFO::LEX_MI_UNCHANGED ||
11231
3/6
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 15 times.
✗ Branch 5 not taken.
15 lex_mi->ssl_key || lex_mi->ssl_cert || lex_mi->ssl_ca ||
11232
3/6
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 15 times.
✗ Branch 5 not taken.
15 lex_mi->ssl_capath || lex_mi->tls_version || lex_mi->ssl_cipher ||
11233
2/4
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
15 lex_mi->ssl_crl || lex_mi->ssl_crlpath ||
11234
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 lex_mi->repl_ignore_server_ids_opt == LEX_MASTER_INFO::LEX_MI_ENABLE ||
11235
2/4
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
15 lex_mi->relay_log_name || lex_mi->relay_log_pos ||
11236
2/4
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
15 lex_mi->sql_delay != -1 || lex_mi->public_key_path ||
11237
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 lex_mi->get_public_key != LEX_MASTER_INFO::LEX_MI_UNCHANGED ||
11238
2/4
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
15 lex_mi->zstd_compression_level || lex_mi->compression_algorithm ||
11239
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 2 times.
15 lex_mi->require_row_format != LEX_MASTER_INFO::LEX_MI_UNCHANGED ||
11240
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 2 times.
13 lex_mi->m_source_connection_auto_failover !=
11241 11 LEX_MASTER_INFO::LEX_MI_UNCHANGED ||
11242
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 lex_mi->assign_gtids_to_anonymous_transactions_type !=
11243 11 LEX_MASTER_INFO::LEX_MI_ANONYMOUS_TO_GTID_UNCHANGED ||
11244
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 9 times.
11 lex_mi->m_gtid_only != LEX_MASTER_INFO::LEX_MI_UNCHANGED)
11245 11 have_extra_option_received = true;
11246
11247 20 return have_extra_option_received;
11248 20 }
11249
11250 /**
11251 Entry point for the CHANGE MASTER command. Function
11252 decides to create a new channel or create an existing one.
11253
11254 @param[in] thd the client thread that issued the command.
11255
11256 @retval true fail
11257 @retval false success.
11258 */
11259 7865 bool change_master_cmd(THD *thd) {
11260
1/2
✓ Branch 0 taken 7865 times.
✗ Branch 1 not taken.
7865 DBUG_TRACE;
11261
11262 7865 Master_info *mi = nullptr;
11263 7865 LEX *lex = thd->lex;
11264 7865 bool res = false;
11265
11266
1/2
✓ Branch 0 taken 7865 times.
✗ Branch 1 not taken.
7865 channel_map.wrlock();
11267
11268 /* The slave must have been initialized to allow CHANGE MASTER statements */
11269
3/4
✓ Branch 0 taken 7865 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 7856 times.
7865 if (!is_slave_configured()) {
11270
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 my_error(ER_SLAVE_CONFIGURATION, MYF(0));
11271 9 res = true;
11272 9 goto err;
11273 }
11274
11275
3/4
✓ Branch 0 taken 7856 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 7836 times.
7856 if (channel_map.is_group_replication_channel_name(lex->mi.channel, true)) {
11276 /*
11277 If the chosen name is for group_replication_applier channel we allow the
11278 channel creation based on the check as to which field is being updated.
11279 */
11280 20 LEX_MASTER_INFO *lex_mi = &thd->lex->mi;
11281
3/4
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 9 times.
20 if (is_invalid_change_master_for_group_replication_applier(lex_mi)) {
11282
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 my_error(ER_SLAVE_CHANNEL_OPERATION_NOT_ALLOWED, MYF(0),
11283 "CHANGE MASTER with the given parameters", lex->mi.channel);
11284 11 res = true;
11285 11 goto err;
11286 }
11287
11288 /*
11289 group_replication_applier channel only has the SQL thread, the IO thread
11290 job is done by GR pipeline, which queues events into the relay log after
11291 going through certification.
11292 Thence for CHANGE MASTER execution pre-conditions we need to check if
11293 the full GR stack is stopped.
11294 */
11295
3/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 8 times.
9 if (is_group_replication_running()) {
11296
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_GRP_OPERATION_NOT_ALLOWED_GR_MUST_STOP, MYF(0));
11297 1 res = true;
11298 1 goto err;
11299 }
11300 }
11301
11302 #ifdef WITH_WSREP
11303 // Similar to GR, do not allow operations on the wsrep channel
11304
6/8
✓ Branch 0 taken 7844 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7844 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 7842 times.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 7842 times.
7844 if (lex->mi.channel && wsrep_is_wsrep_channel_name(lex->mi.channel)) {
11305
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_error(ER_SLAVE_CHANNEL_OPERATION_NOT_ALLOWED, MYF(0),
11306 "CHANGE MASTER with the given parameters", lex->mi.channel);
11307 2 res = true;
11308 2 goto err;
11309 }
11310 #endif /* WITH_WSREP */
11311
11312 // If the channel being used is group_replication_recovery we allow the
11313 // channel creation based on the check as to which field is being updated.
11314
5/6
✓ Branch 0 taken 7842 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1890 times.
✓ Branch 3 taken 5952 times.
✓ Branch 4 taken 1882 times.
✓ Branch 5 taken 5960 times.
9732 if (channel_map.is_group_replication_channel_name(lex->mi.channel) &&
11315
3/4
✓ Branch 0 taken 1890 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1882 times.
✓ Branch 3 taken 8 times.
1890 !channel_map.is_group_replication_channel_name(lex->mi.channel, true)) {
11316 1882 LEX_MASTER_INFO *lex_mi = &thd->lex->mi;
11317
3/4
✓ Branch 0 taken 1882 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 1871 times.
1882 if (is_invalid_change_master_for_group_replication_recovery(lex_mi)) {
11318
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 my_error(ER_SLAVE_CHANNEL_OPERATION_NOT_ALLOWED, MYF(0),
11319 "CHANGE MASTER with the given parameters", lex->mi.channel);
11320 11 res = true;
11321 11 goto err;
11322 }
11323 }
11324
11325 /*
11326 Error out if number of replication channels are > 1 if FOR CHANNEL
11327 clause is not provided in the CHANGE MASTER command.
11328 */
11329
7/8
✓ Branch 0 taken 1725 times.
✓ Branch 1 taken 6106 times.
✓ Branch 2 taken 1725 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 1721 times.
✓ Branch 6 taken 4 times.
✓ Branch 7 taken 7827 times.
7831 if (!lex->mi.for_channel && channel_map.get_num_instances() > 1) {
11330
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 my_error(ER_SLAVE_MULTIPLE_CHANNELS_CMD, MYF(0));
11331 4 res = true;
11332 4 goto err;
11333 }
11334
11335 /* Get the Master_info of the channel */
11336
1/2
✓ Branch 0 taken 7827 times.
✗ Branch 1 not taken.
7827 mi = channel_map.get_mi(lex->mi.channel);
11337
11338 /* create a new channel if doesn't exist */
11339
5/6
✓ Branch 0 taken 2214 times.
✓ Branch 1 taken 5613 times.
✓ Branch 2 taken 2214 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2214 times.
✓ Branch 5 taken 5613 times.
7827 if (!mi && strcmp(lex->mi.channel, channel_map.get_default_channel())) {
11340 /* The mi will be returned holding mi->channel_lock for writing */
11341
3/4
✓ Branch 0 taken 2214 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 2206 times.
2214 if (add_new_channel(&mi, lex->mi.channel)) goto err;
11342 }
11343
11344
1/2
✓ Branch 0 taken 7819 times.
✗ Branch 1 not taken.
7819 if (mi) {
11345 7819 bool configure_filters = !Master_info::is_configured(mi);
11346
11347
3/4
✓ Branch 0 taken 7819 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7674 times.
✓ Branch 3 taken 145 times.
7819 if (!(res = change_master(thd, mi, &thd->lex->mi))) {
11348 /*
11349 If the channel was just created or not configured before this
11350 "CHANGE MASTER", we need to configure rpl_filter for it.
11351 */
11352
2/2
✓ Branch 0 taken 5279 times.
✓ Branch 1 taken 2395 times.
7674 if (configure_filters) {
11353
3/4
✓ Branch 0 taken 5279 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 5272 times.
5279 if ((res = Rpl_info_factory::configure_channel_replication_filters(
11354 mi->rli, lex->mi.channel)))
11355 7 goto err;
11356 }
11357
11358 /*
11359 Issuing deprecation warnings after the change (we make
11360 sure that we don't issue warning if there is an error).
11361 */
11362
1/2
✓ Branch 0 taken 7667 times.
✗ Branch 1 not taken.
7667 issue_deprecation_warnings_for_channel(thd);
11363
11364
1/2
✓ Branch 0 taken 7667 times.
✗ Branch 1 not taken.
7667 my_ok(thd);
11365 }
11366 } else {
11367 /*
11368 Even default channel does not exist. So issue a previous
11369 backward compatible error message (till 5.6).
11370 @TODO: This error message shall be improved.
11371 */
11372 my_error(ER_SLAVE_CONFIGURATION, MYF(0));
11373 }
11374
11375 7865 err:
11376
1/2
✓ Branch 0 taken 7865 times.
✗ Branch 1 not taken.
7865 channel_map.unlock();
11377
11378 7865 return res;
11379 7865 }
11380
11381 /**
11382 Check if there is any slave SQL config conflict.
11383
11384 @param[in] rli The slave's rli object.
11385
11386 @return 0 is returned if there is no conflict, otherwise 1 is returned.
11387 */
11388 19100 static int check_slave_sql_config_conflict(const Relay_log_info *rli) {
11389 int channel_mts_submode, replica_parallel_workers;
11390
11391
2/2
✓ Branch 0 taken 9927 times.
✓ Branch 1 taken 9173 times.
19100 if (rli) {
11392 9927 channel_mts_submode = rli->channel_mts_submode;
11393 9927 replica_parallel_workers = rli->opt_replica_parallel_workers;
11394 } else {
11395 /*
11396 When the slave is first initialized, we collect the values from the
11397 command line options
11398 */
11399 9173 channel_mts_submode = mts_parallel_option;
11400 9173 replica_parallel_workers = opt_mts_replica_parallel_workers;
11401 }
11402
11403
4/4
✓ Branch 0 taken 18919 times.
✓ Branch 1 taken 181 times.
✓ Branch 2 taken 18866 times.
✓ Branch 3 taken 53 times.
19100 if (opt_replica_preserve_commit_order && replica_parallel_workers > 0) {
11404
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 18863 times.
18866 if (channel_mts_submode == MTS_PARALLEL_TYPE_DB_NAME) {
11405 3 my_error(ER_DONT_SUPPORT_REPLICA_PRESERVE_COMMIT_ORDER, MYF(0),
11406 "when replica_parallel_type is DATABASE");
11407 3 return ER_DONT_SUPPORT_REPLICA_PRESERVE_COMMIT_ORDER;
11408 }
11409 }
11410
11411
2/2
✓ Branch 0 taken 9924 times.
✓ Branch 1 taken 9173 times.
19097 if (rli) {
11412 9924 const char *channel = const_cast<Relay_log_info *>(rli)->get_channel();
11413
2/2
✓ Branch 0 taken 9833 times.
✓ Branch 1 taken 46 times.
9879 if (replica_parallel_workers > 0 &&
11414
1/2
✓ Branch 0 taken 9833 times.
✗ Branch 1 not taken.
9833 (channel_mts_submode != MTS_PARALLEL_TYPE_LOGICAL_CLOCK ||
11415 9833 (channel_mts_submode == MTS_PARALLEL_TYPE_LOGICAL_CLOCK &&
11416
6/6
✓ Branch 0 taken 9879 times.
✓ Branch 1 taken 45 times.
✓ Branch 2 taken 94 times.
✓ Branch 3 taken 9739 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 9921 times.
19897 !opt_replica_preserve_commit_order)) &&
11417
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 137 times.
140 channel_map.is_group_replication_channel_name(channel, true)) {
11418 3 my_error(ER_SLAVE_CHANNEL_OPERATION_NOT_ALLOWED, MYF(0),
11419 "START SLAVE SQL_THREAD when REPLICA_PARALLEL_WORKERS > 0 "
11420 "and REPLICA_PARALLEL_TYPE != LOGICAL_CLOCK "
11421 "or REPLICA_PRESERVE_COMMIT_ORDER != ON",
11422 channel);
11423 3 return ER_SLAVE_CHANNEL_OPERATION_NOT_ALLOWED;
11424 }
11425 }
11426
11427 19094 return 0;
11428 }
11429
11430 /**
11431 Purge Group Replication channels relay logs after this server being a
11432 recipient of clone.
11433 */
11434 9173 static void group_replication_cleanup_after_clone() {
11435
5/6
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 9128 times.
✓ Branch 2 taken 45 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 45 times.
✓ Branch 5 taken 9128 times.
9173 if (clone_startup && get_server_state() == SERVER_BOOTING) {
11436
1/2
✓ Branch 0 taken 45 times.
✗ Branch 1 not taken.
45 channel_map.assert_some_wrlock();
11437
1/2
✓ Branch 0 taken 45 times.
✗ Branch 1 not taken.
45 Auto_THD thd;
11438
11439
1/2
✓ Branch 0 taken 45 times.
✗ Branch 1 not taken.
45 Master_info *mi = channel_map.get_mi("group_replication_applier");
11440
3/4
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 34 times.
✗ Branch 3 not taken.
45 if (nullptr != mi) reset_slave(thd.thd, mi, false);
11441
11442
1/2
✓ Branch 0 taken 45 times.
✗ Branch 1 not taken.
45 mi = channel_map.get_mi("group_replication_recovery");
11443
3/4
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 34 times.
✗ Branch 3 not taken.
45 if (nullptr != mi) reset_slave(thd.thd, mi, false);
11444 45 }
11445 9173 }
11446
11447 /**
11448 @} (end of group Replication)
11449 */
11450
11451 /**
11452 Checks the current replica configuration against the server GTID mode
11453 If some incompatibility is found a warning is logged.
11454 */
11455 9173 static void check_replica_configuration_restrictions() {
11456
1/2
✓ Branch 0 taken 9173 times.
✗ Branch 1 not taken.
9173 std::string group_name = get_group_replication_group_name();
11457
7/8
✓ Branch 0 taken 9173 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2195 times.
✓ Branch 3 taken 6978 times.
✓ Branch 4 taken 187 times.
✓ Branch 5 taken 2008 times.
✓ Branch 6 taken 7165 times.
✓ Branch 7 taken 2008 times.
9173 if (global_gtid_mode.get() != Gtid_mode::ON || group_name.length() > 0) {
11458
5/8
✓ Branch 0 taken 7165 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7165 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7206 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 7206 times.
✓ Branch 7 taken 7165 times.
14371 for (auto it : channel_map) {
11459 7206 Master_info *mi = it.second;
11460
1/2
✓ Branch 0 taken 7206 times.
✗ Branch 1 not taken.
7206 if (mi != nullptr) {
11461
3/4
✓ Branch 0 taken 7206 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7012 times.
✓ Branch 3 taken 194 times.
7206 if (global_gtid_mode.get() != Gtid_mode::ON) {
11462 // Check if a channel has SOURCE_AUTO POSITION
11463
7/8
✓ Branch 0 taken 7012 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7007 times.
✓ Branch 3 taken 5 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 7004 times.
✓ Branch 6 taken 3 times.
✓ Branch 7 taken 7009 times.
14019 if (global_gtid_mode.get() == Gtid_mode::OFF &&
11464 7007 mi->is_auto_position()) {
11465
8/16
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 3 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 3 times.
✗ Branch 15 not taken.
3 LogErr(WARNING_LEVEL,
11466 ER_RPL_SLAVE_AUTO_POSITION_IS_1_AND_GTID_MODE_IS_OFF,
11467 mi->get_channel(), mi->get_channel());
11468 }
11469 // Check if a channel has SOURCE_CONNECTION_AUTO_FAILOVER
11470
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 7009 times.
7012 if (mi->is_source_connection_auto_failover()) {
11471
8/16
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 3 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 3 times.
✗ Branch 15 not taken.
3 LogErr(WARNING_LEVEL, ER_RPL_ASYNC_RECONNECT_GTID_MODE_OFF_CHANNEL,
11472 mi->get_channel(), mi->get_channel());
11473 }
11474 // Check if a channel has GTID_ONLY
11475
3/4
✓ Branch 0 taken 7012 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 7011 times.
7012 if (mi->is_gtid_only_mode()) {
11476
8/16
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
1 LogErr(WARNING_LEVEL,
11477 ER_WARN_REPLICA_GTID_ONLY_AND_GTID_MODE_NOT_ON,
11478 mi->get_channel());
11479 }
11480 // Check if a channel has ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS
11481 14024 if (mi->rli->m_assign_gtids_to_anonymous_transactions_info
11482
3/4
✓ Branch 0 taken 7012 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 7010 times.
7012 .get_type() > Assign_gtids_to_anonymous_transactions_info::
11483 enum_type::AGAT_OFF) {
11484 2 std::string assign_gtid_type;
11485 4 if (mi->rli->m_assign_gtids_to_anonymous_transactions_info
11486
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 .get_type() == Assign_gtids_to_anonymous_transactions_info::
11487 enum_type::AGAT_LOCAL)
11488
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 assign_gtid_type.assign("LOCAL");
11489 else
11490 assign_gtid_type.assign("a UUID");
11491
10/20
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 2 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 2 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 2 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 2 times.
✗ Branch 19 not taken.
2 LogErr(
11492 WARNING_LEVEL,
11493 ER_SLAVE_ANONYMOUS_TO_GTID_IS_LOCAL_OR_UUID_AND_GTID_MODE_NOT_ON,
11494 mi->get_channel(), assign_gtid_type.data(),
11495 Gtid_mode::to_string(global_gtid_mode.get()));
11496 2 }
11497 } else {
11498 // No checks needed if mode is OFF
11499 574 if (mi->rli->m_assign_gtids_to_anonymous_transactions_info
11500
3/4
✓ Branch 0 taken 194 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 186 times.
✓ Branch 3 taken 8 times.
194 .get_type() ==
11501 Assign_gtids_to_anonymous_transactions_info::enum_type::AGAT_OFF)
11502 186 continue;
11503
11504 /*
11505 Check if one of the channels with
11506 ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS
11507 does not have the same UUID as Group Replication
11508 */
11509
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (!(group_name.compare(
11510 8 mi->rli->m_assign_gtids_to_anonymous_transactions_info
11511
3/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 6 times.
16 .get_value()))) {
11512
9/18
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 2 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 2 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 2 times.
✗ Branch 17 not taken.
2 LogErr(WARNING_LEVEL,
11513 ER_REPLICA_ANONYMOUS_TO_GTID_UUID_SAME_AS_GROUP_NAME,
11514 mi->get_channel(),
11515 mi->rli->m_assign_gtids_to_anonymous_transactions_info
11516 .get_value()
11517 .c_str());
11518 }
11519 /*
11520 Check if one of the channels with
11521 ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS
11522 does not have the same UUID as group_replication_view_change_uuid
11523 */
11524 8 std::string view_change_uuid;
11525
2/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
8 if (get_group_replication_view_change_uuid(view_change_uuid)) {
11526 /* purecov: begin inspected */
11527 LogErr(WARNING_LEVEL,
11528 ER_WARN_GRP_RPL_VIEW_CHANGE_UUID_FAIL_GET_VARIABLE);
11529 /* purecov: end */
11530 }
11531
11532
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (!(view_change_uuid.compare(
11533 8 mi->rli->m_assign_gtids_to_anonymous_transactions_info
11534
3/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 7 times.
16 .get_value()))) {
11535
9/18
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
1 LogErr(
11536 WARNING_LEVEL,
11537 ER_WARN_REPLICA_ANONYMOUS_TO_GTID_UUID_SAME_AS_VIEW_CHANGE_UUID,
11538 mi->get_channel(),
11539 mi->rli->m_assign_gtids_to_anonymous_transactions_info
11540 .get_value()
11541 .c_str());
11542 }
11543 8 }
11544 }
11545
2/2
✓ Branch 0 taken 7020 times.
✓ Branch 1 taken 186 times.
7206 }
11546 }
11547 9173 }
11548
11549 /**
11550 Checks the current replica configuration when starting a replication thread
11551 If some incompatibility is found an error is thrown.
11552
11553 @param mi pointer to the source info repository object
11554 @param thread_mask what replication threads are running
11555
11556 @return true if an error occurs, false otherwise
11557 */
11558 10754 static bool check_replica_configuration_errors(Master_info *mi,
11559 int thread_mask) {
11560 #ifdef WITH_WSREP
11561
5/6
✓ Branch 0 taken 102 times.
✓ Branch 1 taken 10652 times.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 82 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 20 times.
10754 if (WSREP_ON && !opt_log_replica_updates) {
11562 /*
11563 bad configuration, mysql replication would not be forwarded to wsrep
11564 cluster which would lead to immediate inconsistency
11565 */
11566 WSREP_WARN("Cannot start MySQL slave, when log_slave_updates is not set");
11567 my_error(ER_SLAVE_CONFIGURATION, MYF(0),
11568 "bad configuration no log_slave_updates defined, slave would not"
11569 " replicate further to wsrep cluster");
11570 return true;
11571 }
11572 #endif /* WITH_WSREP */
11573
11574
2/2
✓ Branch 0 taken 5648 times.
✓ Branch 1 taken 5106 times.
10754 if (global_gtid_mode.get() != Gtid_mode::ON) {
11575
5/6
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 5617 times.
✓ Branch 2 taken 31 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 5645 times.
5679 if (mi->is_auto_position() && (thread_mask & SLAVE_IO) &&
11576
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 28 times.
31 global_gtid_mode.get() == Gtid_mode::OFF) {
11577 3 my_error(ER_CANT_USE_AUTO_POSITION_WITH_GTID_MODE_OFF, MYF(0),
11578 3 mi->get_for_channel_str());
11579 3 return true;
11580 }
11581
11582
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 5642 times.
5645 if (mi->is_source_connection_auto_failover()) {
11583 3 my_error(ER_RPL_ASYNC_RECONNECT_GTID_MODE_OFF, MYF(0));
11584 3 return true;
11585 }
11586
11587
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5641 times.
5642 if (mi->is_gtid_only_mode()) {
11588 1 my_error(ER_CANT_USE_GTID_ONLY_WITH_GTID_MODE_NOT_ON, MYF(0),
11589 1 mi->get_for_channel_str());
11590 1 return true;
11591 }
11592
11593
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5640 times.
5641 if ((mi->rli->m_assign_gtids_to_anonymous_transactions_info.get_type() >
11594 Assign_gtids_to_anonymous_transactions_info::enum_type::AGAT_OFF)) {
11595 /*
11596 This function may be called either during server start (when
11597 --skip-start-replica is not used) or during START SLAVE. The error
11598 should only be generated during START SLAVE. During server start, an
11599 error has already been written to the log for this case (in
11600 init_replica).
11601 */
11602
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (current_thd)
11603 1 my_error(ER_CANT_USE_ANONYMOUS_TO_GTID_WITH_GTID_MODE_NOT_ON, MYF(0),
11604 1 mi->get_for_channel_str());
11605 1 return true;
11606 }
11607 }
11608
11609
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 10712 times.
10746 if (mi->rli->m_assign_gtids_to_anonymous_transactions_info.get_type() >
11610 Assign_gtids_to_anonymous_transactions_info::enum_type::AGAT_OFF) {
11611
1/2
✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
34 std::string group_name = get_group_replication_group_name();
11612
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 26 times.
42 if ((group_name.length() > 0) &&
11613
3/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 6 times.
8 !(group_name.compare(
11614 8 mi->rli->m_assign_gtids_to_anonymous_transactions_info
11615
5/8
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 26 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 32 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
42 .get_value()))) {
11616
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_error(ER_ANONYMOUS_TO_GTID_UUID_SAME_AS_GROUP_NAME, MYF(0),
11617 mi->get_channel());
11618 2 return true;
11619 }
11620 32 std::string view_change_uuid;
11621
2/4
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 32 times.
32 if (get_group_replication_view_change_uuid(view_change_uuid)) {
11622 /* purecov: begin inspected */
11623 my_error(ER_GRP_RPL_VIEW_CHANGE_UUID_FAIL_GET_VARIABLE, MYF(0));
11624 return true;
11625 /* purecov: end */
11626 } else {
11627
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 if (!(view_change_uuid.compare(
11628 32 mi->rli->m_assign_gtids_to_anonymous_transactions_info
11629
3/4
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 31 times.
64 .get_value()))) {
11630
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_ANONYMOUS_TO_GTID_UUID_SAME_AS_VIEW_CHANGE_UUID, MYF(0),
11631 mi->get_channel());
11632 1 return true;
11633 }
11634 }
11635
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 1 times.
31 if (mi->rli->until_condition == Relay_log_info::UNTIL_SQL_BEFORE_GTIDS ||
11636
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 mi->rli->until_condition == Relay_log_info::UNTIL_SQL_AFTER_GTIDS) {
11637
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_CANT_SET_SQL_AFTER_OR_BEFORE_GTIDS_WITH_ANONYMOUS_TO_GTID,
11638 MYF(0));
11639 1 return true;
11640 }
11641
4/4
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 30 times.
✓ Branch 3 taken 4 times.
36 }
11642 10742 return false;
11643 }
11644